/** Expect to see two diagonal lines overlaying a wall texture cube. One line should run from green at the top left to red at the bottom right. The other should run from cyan 100% transparent at the bottom left to cyan 100% opaque at the top right. */ static bool lineRender(E_DRIVER_TYPE driverType) { IrrlichtDevice *device = createDevice( driverType, dimension2d<u32>(160, 120), 32); if (!device) return true; // Treat a failure to create a driver as benign; this saves a lot of #ifdefs IVideoDriver* driver = device->getVideoDriver(); ISceneManager * smgr = device->getSceneManager(); stabilizeScreenBackground(driver); logTestString("Testing driver %ls\n", driver->getName()); // Draw a cube background so that we can check that the pixels' alpha is working. ISceneNode * cube = smgr->addCubeSceneNode(50.f, 0, -1, vector3df(0, 0, 60)); cube->setMaterialTexture(0, driver->getTexture("../media/wall.bmp")); cube->setMaterialFlag(video::EMF_LIGHTING, false); (void)smgr->addCameraSceneNode(); driver->beginScene(true, true, SColor(255,100,101,140)); smgr->drawAll(); // Test for benign handling of offscreen pixel values as well as onscreen ones. for(s32 x = -10; x < 170; ++x) { s32 y = 120 * x / 160; driver->drawPixel((u32)x, (u32)y, SColor(255, 255 * x / 640, 255 * (640 - x) / 640, 0)); y = 120 - y; driver->drawPixel((u32)x, (u32)y, SColor(255 * x / 640, 0, 255, 255)); } driver->endScene(); bool result = takeScreenshotAndCompareAgainstReference(driver, "-drawPixel.png", 98.81f); device->closeDevice(); device->run(); device->drop(); return result; }
bool serializeAttributes() { bool result = true; IrrlichtDevice * device = irr::createDevice(video::EDT_NULL, dimension2d<u32>(1, 1)); assert(device); if(!device) { logTestString("device creation failed in %s:%d\n", __FILE__, __LINE__ ); return false; } io::IFileSystem * fs = device->getFileSystem (); if ( !fs ) { return false; } result &= MemorySerialization(fs); if ( !result ) { logTestString("MemorySerialization failed in %s:%d\n", __FILE__, __LINE__ ); } result &= XmlSerialization(fs, device->getVideoDriver()); if ( !result ) { logTestString("XmlSerialization failed in %s:%d\n", __FILE__, __LINE__ ); } device->closeDevice(); device->run(); device->drop(); return result; }
int main() { // ask user for driver video::E_DRIVER_TYPE driverType = driverChoiceConsole(); if (driverType == video::EDT_COUNT) return 1; // create device with full flexibility over creation parameters // you can add more parameters if desired, check irr::SIrrlichtCreationParameters irr::SIrrlichtCreationParameters params; params.DriverType = driverType; params.WindowSize = core::dimension2d<u32>(1024, 768); IrrlichtDevice* device = createDeviceEx(params); if (device == 0) return 1; // could not create selected driver. video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* env = device->getGUIEnvironment(); env->getSkin()->setFont(env->getFont("media/fontlucida.png")); driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true); // Add camera scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(0, 100.0f, 0.05f); camera->setPosition(core::vector3df(820, 100, 850)); camera->setTarget(core::vector3df(1530, 708, 1296)); camera->setFarValue(42000.0f); // camera->setPosition(core::vector3df(50,50,-60)); // camera->setTarget(core::vector3df(-70,30,-60)); // disable mouse cursor device->getCursorControl()->setVisible(false); // Add terrain scene node scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode("media/terrain-heightmap.bmp", 0, // parent node -1, // node id core::vector3df(0.f, 0.f, 0.f), // position core::vector3df(0.f, 0.f, 0.f), // rotation core::vector3df(7.f, 1.f, 7.f), // scale video::SColor(255, 255, 255, 255), // vertexColor 5, // maxLOD scene::ETPS_17, // patchSize 4 // smoothFactor ); terrain->setMaterialFlag(video::EMF_LIGHTING, false); terrain->setMaterialTexture(0, driver->getTexture("media/terrain-texture.jpg")); terrain->setMaterialTexture(1, driver->getTexture("media/detailmap3.jpg")); terrain->setMaterialType(video::EMT_DETAIL_MAP); terrain->scaleTexture(1.0f, 100.0f); // create triangle selector for the terrain scene::ITriangleSelector* selector = smgr->createTerrainTriangleSelector(terrain, 0); terrain->setTriangleSelector(selector); // create collision response animator and attach it to the camera scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(selector, camera, core::vector3df(1, 1, 1), core::vector3df(0, 0, 0)); selector->drop(); camera->addAnimator(anim); anim->drop(); // sphere scene::IMeshSceneNode* sphere = smgr->addSphereSceneNode(25.f, 100); sphere->setPosition(core::vector3df(800, 100, 800)); sphere->setScale(core::vector3df(2, 2, 2)); // Create decal manager DecalManager* decalManager = new DecalManager(smgr); decalManager->setTerrain(terrain); decalManager->addMesh(sphere); MyEventReceiver* receiver = new MyEventReceiver(decalManager, terrain, sphere); device->setEventReceiver(receiver); irr::video::SColor backgroundColor(10, 255, 255, 255); irr::video::SColor textColor(255, 255, 255, 255); int lastFPS = -1; irr::core::vector3df position = irr::core::vector3df(800, 300, 800); irr::core::vector3df dimension = irr::core::vector3df(1, 1, 1); irr::core::vector3df normal = irr::core::vector3df(1, 1, 0); irr::f32 textureRotation = 0; irr::scene::ISceneNode* parent = 0; irr::f32 lifeTime = 110; irr::f32 distance = 110; // decalManager->addDecal("media/decal.png", collisionPoint, irr::core::vector3df(size, size, size), normal, rotation, parent, lifetime, distance); decalManager->addDecal("media/decal.png", position, dimension, normal, textureRotation, parent, lifeTime, distance); while (device->run()) { if (device->isWindowActive()) { driver->beginScene(true, true, 0); smgr->drawAll(); env->getVideoDriver()->draw2DRectangle(backgroundColor, irr::core::rect<s32>(0, 0, 280, 220)); irr::core::stringw str = "SIZE: "; str += (irr::u32) receiver->size; str += " [ S & D ]"; env->getSkin()->getFont()->draw(str.c_str(), irr::core::rect<s32>(10, 10, 200, 20), textColor, false, true); str = "LIFETIME: "; str += (irr::u32) receiver->lifetime; str += " [ O & L ]"; env->getSkin()->getFont()->draw(str.c_str(), irr::core::rect<s32>(10, 30, 200, 50), textColor, false, true); str = "DISTANCE: "; str += (irr::u32) receiver->distance; str += " [ I & K ]"; env->getSkin()->getFont()->draw(str.c_str(), irr::core::rect<s32>(10, 60, 200, 80), textColor, false, true); str = "ROTATION: "; str += (irr::u32) receiver->rotation; str += " [ R or R Mouse Button ]"; env->getSkin()->getFont()->draw(str.c_str(), irr::core::rect<s32>(10, 90, 200, 110), textColor, false, true); str = "COMBINE [C]"; env->getSkin()->getFont()->draw(str.c_str(), irr::core::rect<s32>(10, 120, 200, 140), textColor, false, true); str = "DECAL NORMAL: "; if (receiver->useCameraNormal) { str += "CAMERA DIRECTION"; } else { str += "HIT TRIANGLE"; } str += " [ N ]"; env->getSkin()->getFont()->draw(str.c_str(), irr::core::rect<s32>(10, 150, 200, 170), textColor, false, true); str = "SPHERE AS PARENT: "; if (receiver->useParent) { str += "YES"; } else { str += "NO"; } str += " [ P ]"; env->getSkin()->getFont()->draw(str.c_str(), irr::core::rect<s32>(10, 180, 200, 200), textColor, false, true); irr::video::SColor color = irr::video::SColor(255, 255, 255, 255); u32 size = 15; irr::u32 cenW = (irr::u32) (driver->getScreenSize().Width * 0.5); irr::u32 cenH = (irr::u32) (driver->getScreenSize().Height * 0.5); //Draw crosshair driver->draw2DRectangle(color, irr::core::rect<irr::s32>(cenW - 1, cenH - size, cenW + 1, cenH - 4)); //above driver->draw2DRectangle(color, irr::core::rect<irr::s32>(cenW + 4, cenH - 1, cenW + size, cenH + 1)); //right driver->draw2DRectangle(color, irr::core::rect<irr::s32>(cenW - 1, cenH + 4, cenW + 1, cenH + size)); //down driver->draw2DRectangle(color, irr::core::rect<irr::s32>(cenW - size, cenH - 1, cenW - 4, cenH + 1)); //left driver->draw2DRectangle(color, irr::core::rect<irr::s32>(cenW - 1, cenH - 1, cenW + 1, cenH + 1)); //center of screen env->drawAll(); driver->endScene(); // display frames per second in window title int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"TANK@WAR DecalManager ["; str += driver->getName(); str += "] FPS:"; str += fps; str += " Nodes: "; str += smgr->getRootSceneNode()->getChildren().size(); str += " Primitives: "; str += driver->getPrimitiveCountDrawn(); device->setWindowCaption(str.c_str()); lastFPS = fps; } } } device->drop(); return 0; }
/* OK, now for the more interesting part. First, create the Irrlicht device. As in some examples before, we ask the user which driver he wants to use for this example. */ int main() { // create device and exit if creation failed IrrlichtDevice * device = createDevice(EDT_OPENGL,core::dimension2d<u32>(640, 480)); if (device == 0) return 1; // could not create selected driver. /* The creation was successful, now we set the event receiver and store pointers to the driver and to the gui environment. */ device->setWindowCaption(L"Irrlicht Engine - User Interface Demo"); device->setResizable(true); video::IVideoDriver* driver = device->getVideoDriver(); IGUIEnvironment* env = device->getGUIEnvironment(); const io::path mediaPath = getExampleMediaPath(); /* To make the font a little bit nicer, we load an external font and set it as the new default font in the skin. To keep the standard font for tool tip text, we set it to the built-in font. */ IGUISkin* skin = env->getSkin(); IGUIFont* font = env->getFont(mediaPath + "fonthaettenschweiler.bmp"); if (font) skin->setFont(font); skin->setFont(env->getBuiltInFont(), EGDF_TOOLTIP); /* We add three buttons. The first one closes the engine. The second creates a window and the third opens a file open dialog. The third parameter is the id of the button, with which we can easily identify the button in the event receiver. */ env->addButton(rect<s32>(10,240,110,240 + 32), 0, GUI_ID_QUIT_BUTTON, L"Quit", L"Exits Program"); env->addButton(rect<s32>(10,280,110,280 + 32), 0, GUI_ID_NEW_WINDOW_BUTTON, L"New Window", L"Launches a new Window"); env->addButton(rect<s32>(10,320,110,320 + 32), 0, GUI_ID_FILE_OPEN_BUTTON, L"File Open", L"Opens a file"); /* Now, we add a static text and a scrollbar, which modifies the transparency of all gui elements. We set the maximum value of the scrollbar to 255, because that's the maximal value for a color value. Then we create an other static text and a list box. */ env->addStaticText(L"Transparent Control:", rect<s32>(150,20,350,40), true); IGUIScrollBar* scrollbar = env->addScrollBar(true, rect<s32>(150, 45, 350, 60), 0, GUI_ID_TRANSPARENCY_SCROLL_BAR); scrollbar->setMax(255); scrollbar->setPos(255); setSkinTransparency( scrollbar->getPos(), env->getSkin()); // set scrollbar position to alpha value of an arbitrary element scrollbar->setPos(env->getSkin()->getColor(EGDC_WINDOW).getAlpha()); env->addStaticText(L"Logging ListBox:", rect<s32>(10,110,350,130), true); IGUIListBox * listbox = env->addListBox(rect<s32>(10, 140, 350, 210)); env->addEditBox(L"Editable Text", rect<s32>(350, 80, 550, 100)); // Store the appropriate data in a context structure. SAppContext context; context.device = device; context.counter = 0; context.listbox = listbox; // Then create the event receiver, giving it that context structure. MyEventReceiver receiver(context); // And tell the device to use our custom event receiver. device->setEventReceiver(&receiver); /* And at last, we create a nice Irrlicht Engine logo in the top left corner. */ env->addImage(driver->getTexture(mediaPath + "irrlichtlogo2.png"), position2d<int>(10,10)); /* That's all, we only have to draw everything. */ fluid_settings_t* settings; // int arg1 = 1; char buf[512]; // int c, i; int interactive = 1; int midi_in = 1; fluid_player_t* player = NULL; fluid_midi_router_t* router = NULL; //fluid_sequencer_t* sequencer = NULL; fluid_midi_driver_t* mdriver = NULL; fluid_audio_driver_t* adriver = NULL; fluid_synth_t* synth = NULL; #ifdef NETWORK_SUPPORT fluid_server_t* server = NULL; int with_server = 0; #endif char* config_file = NULL; int audio_groups = 0; int audio_channels = 0; int dump = 0; int fast_render = 0; static const char optchars[] = "a:C:c:dE:f:F:G:g:hijK:L:lm:nO:o:p:R:r:sT:Vvz:"; #ifdef LASH_ENABLED int connect_lash = 1; int enabled_lash = 0; /* set to TRUE if lash gets enabled */ fluid_lash_args_t *lash_args; lash_args = fluid_lash_extract_args (&argc, &argv); #endif settings = new_fluid_settings(); /* The 'groups' setting is relevant for LADSPA operation and channel mapping * in rvoice_mixer. * If not given, set number groups to number of audio channels, because * they are the same (there is nothing between synth output and 'sound card') */ if ((audio_groups == 0) && (audio_channels != 0)) { audio_groups = audio_channels; } if (audio_groups != 0) { fluid_settings_setint(settings, "synth.audio-groups", audio_groups); } if (fast_render) { midi_in = 0; interactive = 0; #ifdef NETWORK_SUPPORT with_server = 0; #endif fluid_settings_setstr(settings, "player.timing-source", "sample"); fluid_settings_setint(settings, "synth.lock-memory", 0); } /* create the synthesizer */ synth = new_fluid_synth(settings); if (synth == NULL) { fprintf(stderr, "Failed to create the synthesizer\n"); exit(-1); } /* load the soundfonts (check that all non options are SoundFont or MIDI files) */ // for (i = arg1; i < argc; i++) { if (fluid_is_soundfont(psoundfont)) { if (fluid_synth_sfload(synth, psoundfont, 1) == -1) fprintf(stderr, "Failed to load the SoundFont %s\n", psoundfont); } else if (!fluid_is_midifile(psoundfont)) fprintf (stderr, "Parameter '%s' not a SoundFont or MIDI file or error occurred identifying it.\n", psoundfont); /* start the synthesis thread */ if (!fast_render) { fluid_settings_setstr(settings, "audio.driver", "alsa"); adriver = new_fluid_audio_driver(settings, synth); if (adriver == NULL) { fprintf(stderr, "Failed to create the audio driver\n"); // goto cleanup; } } /* start the midi router and link it to the synth */ #if WITH_MIDI if (midi_in) { /* In dump mode, text output is generated for events going into and out of the router. * The example dump functions are put into the chain before and after the router.. */ //sequencer = new_fluid_sequencer2(0); router = new_fluid_midi_router( settings, dump ? fluid_midi_dump_postrouter : fluid_synth_handle_midi_event, (void*)synth); if (router == NULL) { fprintf(stderr, "Failed to create the MIDI input router; no MIDI input\n" "will be available. You can access the synthesizer \n" "through the console.\n"); } else { mdriver = new_fluid_midi_driver( settings, dump ? fluid_midi_dump_prerouter : fluid_midi_router_handle_midi_event, (void*) router); if (mdriver == NULL) { fprintf(stderr, "Failed to create the MIDI thread; no MIDI input\n" "will be available. You can access the synthesizer \n" "through the console.\n"); } } } #endif /* play the midi fildes, if any */ // for (i = arg1; i < argc; i++) { if (fluid_is_midifile(psong)) { if (player == NULL) { player = new_fluid_player(synth); if (player == NULL) { fprintf(stderr, "Failed to create the midifile player.\n" "Continuing without a player.\n"); // break; } } fluid_player_add(player, psong); } // } if (player != NULL) { if (fluid_synth_get_sfont(synth, 0) == NULL) { /* Try to load the default soundfont if no soundfont specified */ char *s; if (fluid_settings_dupstr(settings, "synth.default-soundfont", &s) != FLUID_OK) s = NULL; if ((s != NULL) && (s[0] != '\0')) fluid_synth_sfload(synth, s, 1); FLUID_FREE(s); } fluid_player_play(player); } cmd_handler = new_fluid_cmd_handler(synth, router); if (cmd_handler == NULL) { fprintf(stderr, "Failed to create the command handler\n"); // goto cleanup; } /* try to load the user or system configuration */ if (config_file != NULL) { fluid_source(cmd_handler, config_file); } else if (fluid_get_userconf(buf, sizeof(buf)) != NULL) { fluid_source(cmd_handler, buf); } else if (fluid_get_sysconf(buf, sizeof(buf)) != NULL) { fluid_source(cmd_handler, buf); } /* run the server, if requested */ #ifdef NETWORK_SUPPORT if (with_server) { server = new_fluid_server(settings, synth, router); if (server == NULL) { fprintf(stderr, "Failed to create the server.\n" "Continuing without it.\n"); } } #endif #ifdef LASH_ENABLED if (enabled_lash) fluid_lash_create_thread (synth); #endif while(device->run() && driver) if (device->isWindowActive()) { driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, SColor(0,200,200,200)); env->drawAll(); //fast_render; // if (fast_render) { // char *filename; // if (player == NULL) { // fprintf(stderr, "No midi file specified!\n"); // // fluid_player_play(player); //// goto cleanup; // } // // fluid_settings_dupstr (settings, "audio.file.name", &filename); // printf ("Rendering audio to file '%s'..\n", filename); // if (filename) FLUID_FREE (filename); // // fast_render_loop(settings, synth, player); // } /* Play a note */ // fluid_synth_noteon(synth, 0, 60, 100); // printf("Press \"Enter\" to stop: "); // fgetc(stdin); // printf("done\n"); device->sleep(129); driver->endScene(); } if (adriver) { delete_fluid_audio_driver(adriver); } if (synth) { delete_fluid_synth(synth); } if (settings) { delete_fluid_settings(settings); } device->drop(); return 0; }
void QuakeShaderInitScene() { if (!IrrlichtManager::GetIrrlichtManager()->GetDevice()) { LogError("Error initializing Irrlicht"); return; } IrrlichtManager::GetIrrlichtManager()->GetDevice()->getTimer()->setTime(0); scene::ISceneManager* smgr = IrrlichtManager::GetIrrlichtManager()->GetScene(); IrrlichtDevice* device = IrrlichtManager::GetIrrlichtManager()->GetDevice(); // Quake3 Shader controls Z-Writing smgr->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true); //for Android FileSystemZip* pFileSystem = (FileSystemZip*) FileManager::GetFileManager()->GetFileSystem(0); //for Android if (pFileSystem) pFileSystem->SetRootDirectory("assets/game/quake"); //hack so the textures can be found. The quake map loader isn't all that smart device->getFileSystem()->changeWorkingDirectoryTo((GetBaseAppPath() + "game/quake").c_str()); u32 i; scene::IQ3LevelMesh* mesh; scene::IMeshSceneNode* node; scene::IMesh* geometry; const scene::IMesh* additional_mesh; mesh = (scene::IQ3LevelMesh*)smgr->getMesh("maps/20kdm2.bsp"); if (mesh) { geometry = mesh->getMesh(quake3::E_Q3_MESH_GEOMETRY); node = smgr->addOctreeSceneNode(geometry, 0, -1, 4096); } if ( mesh ) { // the additional mesh can be quite huge and is unoptimized additional_mesh = mesh->getMesh(quake3::E_Q3_MESH_ITEMS); #ifdef SHOW_SHADER_NAME gui::IGUIFont *font = device->getGUIEnvironment()->getFont("media/fontlucida.png"); u32 count = 0; #endif for ( i = 0; i!= additional_mesh->getMeshBufferCount(); ++i ) { const IMeshBuffer* meshBuffer = additional_mesh->getMeshBuffer(i); const video::SMaterial& material = meshBuffer->getMaterial(); // The ShaderIndex is stored in the material parameter const s32 shaderIndex = (s32) material.MaterialTypeParam2; // the meshbuffer can be rendered without additional support, or it has no shader const quake3::IShader* shader = mesh->getShader(shaderIndex); if (0 == shader) { continue; } // we can dump the shader to the console in its // original but already parsed layout in a pretty // printers way.. commented out, because the console // would be full... // quake3::dumpShader ( Shader ); node = smgr->addQuake3SceneNode(meshBuffer, shader); #ifdef SHOW_SHADER_NAME count += 1; core::stringw name( node->getName() ); node = smgr->addBillboardTextSceneNode( font, name.c_str(), node, core::dimension2d<f32>(80.0f, 8.0f), core::vector3df(0, 10, 0)); #endif } } quake3::IEntity search; s32 index; s32 notEndList; u32 parsepos; f32 angle; core::vector3df pos; const quake3::SVarGroup* group; scene::ICameraSceneNode* camera; camera = smgr->addCameraSceneNodeFPS(); if ( mesh ) { quake3::tQ3EntityList& entityList = mesh->getEntityList(); search.name = "info_player_deathmatch"; index = entityList.binary_search(search); if (index >= 0) { do { group = entityList[index].getGroup(1); parsepos = 0; pos = quake3::getAsVector3df(group->get("origin"), parsepos); parsepos = 0; angle = quake3::getAsFloat(group->get("angle"), parsepos); core::vector3df target(0.f, 0.f, 1.f); target.rotateXZBy(angle); camera->setPosition(pos); camera->setTarget(pos + target); ++index; notEndList = index == 2; } while ( notEndList ); } } #ifdef _IRR_COMPILE_WITH_GUI_ EventControlComponent* receiver = new EventControlComponent(); receiver->AddGuiButton(); device->setEventReceiver(receiver); #endif }
virtual scene::IAnimatedMesh * createMesh (io::IReadFile *file) { video::IVideoDriver * driver = m_device->getVideoDriver(); intrusive_ptr<video::IImage> img = intrusive_ptr<video::IImage>(driver->createImageFromFile(file), false); if(!img) { return false; } core::dimension2d<u32> size = img->getDimension(); intrusive_ptr<scene::SMesh> mesh(new scene::SMesh, false); intrusive_ptr<scene::IAnimatedMesh> animmesh(new scene::SAnimatedMesh(get_pointer(mesh)), false); const u32 meshbuffer_size = driver -> getMaximalPrimitiveCount(); int rows_per_buffer = meshbuffer_size / ((size.Width-1) * 2); int trianglecount = 2 * (size.Width-1) * (size.Height-1); int buffercount = trianglecount/meshbuffer_size+1; for(int i = 0; i < buffercount; i++) { int starty = rows_per_buffer*i; int endy = rows_per_buffer*(i+1); if(endy > size.Height)endy = size.Height; // create new buffer... scene::SMeshBuffer * buffer = new scene::SMeshBuffer; mesh->addMeshBuffer(buffer); buffer->drop(); // now owned by mesh buffer->Vertices.set_used((1 + endy - starty) * size.Width); int idx = 0; for(int y = starty; y < endy; y++) { for(int x = 0; x < size.Width; x++) { // center the model around -0.5 -> 0.5 on every axis float pz = get_height(get_pointer(img), x, y); float px = float(x)/(size.Width-1); float py = float(y)/(size.Height-1); video::S3DVertex& v = buffer->Vertices[idx++]; v.Pos.set(-0.5+px, -0.5+py, -0.5+pz); v.Normal.set(0,0,1); if(x < size.Width-1) v.Normal.X -= size.Width/(get_height(get_pointer(img), x+1, y)-get_height(get_pointer(img), x, y)); if(x > 0) v.Normal.X += size.Width/(get_height(get_pointer(img), x-1, y)-get_height(get_pointer(img), x, y)); if(y < size.Height-1) v.Normal.Y -= size.Height/(get_height(get_pointer(img), x, y+1)-get_height(get_pointer(img), x, y)); if(y > 0) v.Normal.Y += size.Height/(get_height(get_pointer(img), x, y-1)-get_height(get_pointer(img), x, y)); v.Normal.normalize(); v.Color.set(255,255,255,255); v.TCoords.set(px, py); } } idx = 0; buffer->Indices.set_used(6 * (size.Width-1) * (endy-starty)); for(int y = starty; y < endy; y++) { for(int x = 0; x < size.Width-1; x++) { int n = (y-starty) * size.Width + x; buffer->Indices[idx++] = n; buffer->Indices[idx++] = n + size.Height + 1; buffer->Indices[idx++] = n + size.Height; buffer->Indices[idx++] = n + size.Height + 1; buffer->Indices[idx++] = n; buffer->Indices[idx++] = n + 1; } } buffer -> recalculateBoundingBox(); } // make animmesh outlive this scope animmesh->grab(); return get_pointer(animmesh); }
int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // create device IrrlichtDevice *device = createDevice(driverType, core::dimension2d<u32>(640, 480), 16, false); if (device == 0) return 1; // could not create selected driver. video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); const io::path mediaPath = getExampleMediaPath(); device->getFileSystem()->addFileArchive(mediaPath + "map-20kdm2.pk3"); scene::IAnimatedMesh* q3levelmesh = smgr->getMesh("20kdm2.bsp"); scene::IMeshSceneNode* q3node = 0; // The Quake mesh is pickable, but doesn't get highlighted. if (q3levelmesh) q3node = smgr->addOctreeSceneNode(q3levelmesh->getMesh(0), 0, IDFlag_IsPickable); /* So far so good, we've loaded the quake 3 level like in tutorial 2. Now, here comes something different: We create a triangle selector. A triangle selector is a class which can fetch the triangles from scene nodes for doing different things with them, for example collision detection. There are different triangle selectors, and all can be created with the ISceneManager. In this example, we create an OctreeTriangleSelector, which optimizes the triangle output a little bit by reducing it like an octree. This is very useful for huge meshes like quake 3 levels. After we created the triangle selector, we attach it to the q3node. This is not necessary, but in this way, we do not need to care for the selector, for example dropping it after we do not need it anymore. */ scene::ITriangleSelector* selector = 0; if (q3node) { q3node->setPosition(core::vector3df(-1350,-130,-1400)); selector = smgr->createOctreeTriangleSelector( q3node->getMesh(), q3node, 128); q3node->setTriangleSelector(selector); // We're not done with this selector yet, so don't drop it. } /* We add a first person shooter camera to the scene so that we can see and move in the quake 3 level like in tutorial 2. But this, time, we add a special animator to the camera: A Collision Response animator. This animator modifies the scene node to which it is attached to in order to prevent it moving through walls, and to add gravity to it. The only thing we have to tell the animator is how the world looks like, how big the scene node is, how much gravity to apply and so on. After the collision response animator is attached to the camera, we do not have to do anything more for collision detection, anything is done automatically. The rest of the collision detection code below is for picking. And please note another cool feature: The collision response animator can be attached also to all other scene nodes, not only to cameras. And it can be mixed with other scene node animators. In this way, collision detection and response in the Irrlicht engine is really easy. Now we'll take a closer look on the parameters of createCollisionResponseAnimator(). The first parameter is the TriangleSelector, which specifies how the world, against collision detection is done looks like. The second parameter is the scene node, which is the object, which is affected by collision detection, in our case it is the camera. The third defines how big the object is, it is the radius of an ellipsoid. Try it out and change the radius to smaller values, the camera will be able to move closer to walls after this. The next parameter is the direction and speed of gravity. We'll set it to (0, -10, 0), which approximates to realistic gravity, assuming that our units are metres. You could set it to (0,0,0) to disable gravity. And the last value is just a translation: Without this, the ellipsoid with which collision detection is done would be around the camera, and the camera would be in the middle of the ellipsoid. But as human beings, we are used to have our eyes on top of the body, with which we collide with our world, not in the middle of it. So we place the scene node 50 units over the center of the ellipsoid with this parameter. And that's it, collision detection works now. */ // Set a jump speed of 3 units per second, which gives a fairly realistic jump // when used with the gravity of (0, -10, 0) in the collision response animator. scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(0, 100.0f, .3f, ID_IsNotPickable, 0, 0, true, 3.f); camera->setPosition(core::vector3df(50,50,-60)); camera->setTarget(core::vector3df(-70,30,-60)); if (selector) { scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator( selector, camera, core::vector3df(30,50,30), core::vector3df(0,-10,0), core::vector3df(0,30,0)); selector->drop(); // As soon as we're done with the selector, drop it. camera->addAnimator(anim); anim->drop(); // And likewise, drop the animator when we're done referring to it. } // Now I create three animated characters which we can pick, a dynamic light for // lighting them, and a billboard for drawing where we found an intersection. // First, let's get rid of the mouse cursor. We'll use a billboard to show // what we're looking at. device->getCursorControl()->setVisible(false); // Add the billboard. scene::IBillboardSceneNode * bill = smgr->addBillboardSceneNode(); bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR ); bill->setMaterialTexture(0, driver->getTexture(mediaPath + "particle.bmp")); bill->setMaterialFlag(video::EMF_LIGHTING, false); bill->setMaterialFlag(video::EMF_ZBUFFER, false); bill->setSize(core::dimension2d<f32>(20.0f, 20.0f)); bill->setID(ID_IsNotPickable); // This ensures that we don't accidentally ray-pick it /* Add 3 animated hominids, which we can pick using a ray-triangle intersection. They all animate quite slowly, to make it easier to see that accurate triangle selection is being performed. */ scene::IAnimatedMeshSceneNode* node = 0; video::SMaterial material; // Add an MD2 node, which uses vertex-based animation. node = smgr->addAnimatedMeshSceneNode(smgr->getMesh(mediaPath + "faerie.md2"), 0, IDFlag_IsPickable | IDFlag_IsHighlightable); node->setPosition(core::vector3df(-90,-15,-140)); // Put its feet on the floor. node->setScale(core::vector3df(1.6f)); // Make it appear realistically scaled node->setMD2Animation(scene::EMAT_POINT); node->setAnimationSpeed(20.f); material.setTexture(0, driver->getTexture(mediaPath + "faerie2.bmp")); material.Lighting = true; material.NormalizeNormals = true; node->getMaterial(0) = material; // Now create a triangle selector for it. The selector will know that it // is associated with an animated node, and will update itself as necessary. selector = smgr->createTriangleSelector(node); node->setTriangleSelector(selector); selector->drop(); // We're done with this selector, so drop it now. // And this B3D file uses skinned skeletal animation. node = smgr->addAnimatedMeshSceneNode(smgr->getMesh(mediaPath + "ninja.b3d"), 0, IDFlag_IsPickable | IDFlag_IsHighlightable); node->setScale(core::vector3df(10)); node->setPosition(core::vector3df(-75,-66,-80)); node->setRotation(core::vector3df(0,90,0)); node->setAnimationSpeed(8.f); node->getMaterial(0).NormalizeNormals = true; node->getMaterial(0).Lighting = true; // Just do the same as we did above. selector = smgr->createTriangleSelector(node); node->setTriangleSelector(selector); selector->drop(); // This X files uses skeletal animation, but without skinning. node = smgr->addAnimatedMeshSceneNode(smgr->getMesh(mediaPath + "dwarf.x"), 0, IDFlag_IsPickable | IDFlag_IsHighlightable); node->setPosition(core::vector3df(-70,-66,-30)); // Put its feet on the floor. node->setRotation(core::vector3df(0,-90,0)); // And turn it towards the camera. node->setAnimationSpeed(20.f); node->getMaterial(0).Lighting = true; selector = smgr->createTriangleSelector(node); node->setTriangleSelector(selector); selector->drop(); // And this mdl file uses skinned skeletal animation. node = smgr->addAnimatedMeshSceneNode(smgr->getMesh(mediaPath + "yodan.mdl"), 0, IDFlag_IsPickable | IDFlag_IsHighlightable); node->setPosition(core::vector3df(-90,-25,20)); node->setScale(core::vector3df(0.8f)); node->getMaterial(0).Lighting = true; node->setAnimationSpeed(20.f); // Just do the same as we did above. selector = smgr->createTriangleSelector(node); node->setTriangleSelector(selector); selector->drop(); material.setTexture(0, 0); material.Lighting = false; // Add a light, so that the unselected nodes aren't completely dark. scene::ILightSceneNode * light = smgr->addLightSceneNode(0, core::vector3df(-60,100,400), video::SColorf(1.0f,1.0f,1.0f,1.0f), 600.0f); light->setID(ID_IsNotPickable); // Make it an invalid target for selection. // Remember which scene node is highlighted scene::ISceneNode* highlightedSceneNode = 0; scene::ISceneCollisionManager* collMan = smgr->getSceneCollisionManager(); int lastFPS = -1; // draw the selection triangle only as wireframe material.Wireframe=true; while(device->run()) if (device->isWindowActive()) { driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(0)); smgr->drawAll(); // Unlight any currently highlighted scene node if (highlightedSceneNode) { highlightedSceneNode->setMaterialFlag(video::EMF_LIGHTING, true); highlightedSceneNode = 0; } // All intersections in this example are done with a ray cast out from the camera to // a distance of 1000. You can easily modify this to check (e.g.) a bullet // trajectory or a sword's position, or create a ray from a mouse click position using // ISceneCollisionManager::getRayFromScreenCoordinates() core::line3d<f32> ray; ray.start = camera->getPosition(); ray.end = ray.start + (camera->getTarget() - ray.start).normalize() * 1000.0f; // Tracks the current intersection point with the level or a mesh core::vector3df intersection; // Used to show with triangle has been hit core::triangle3df hitTriangle; // This call is all you need to perform ray/triangle collision on every scene node // that has a triangle selector, including the Quake level mesh. It finds the nearest // collision point/triangle, and returns the scene node containing that point. // Irrlicht provides other types of selection, including ray/triangle selector, // ray/box and ellipse/triangle selector, plus associated helpers. // See the methods of ISceneCollisionManager scene::ISceneNode * selectedSceneNode = collMan->getSceneNodeAndCollisionPointFromRay( ray, intersection, // This will be the position of the collision hitTriangle, // This will be the triangle hit in the collision IDFlag_IsPickable, // This ensures that only nodes that we have // set up to be pickable are considered 0); // Check the entire scene (this is actually the implicit default) // If the ray hit anything, move the billboard to the collision position // and draw the triangle that was hit. if(selectedSceneNode) { bill->setPosition(intersection); // We need to reset the transform before doing our own rendering. driver->setTransform(video::ETS_WORLD, core::matrix4()); driver->setMaterial(material); driver->draw3DTriangle(hitTriangle, video::SColor(0,255,0,0)); // We can check the flags for the scene node that was hit to see if it should be // highlighted. The animated nodes can be highlighted, but not the Quake level mesh if((selectedSceneNode->getID() & IDFlag_IsHighlightable) == IDFlag_IsHighlightable) { highlightedSceneNode = selectedSceneNode; // Highlighting in this case means turning lighting OFF for this node, // which means that it will be drawn with full brightness. highlightedSceneNode->setMaterialFlag(video::EMF_LIGHTING, false); } } // We're all done drawing, so end the scene. driver->endScene(); int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Collision detection example - Irrlicht Engine ["; str += driver->getName(); str += "] FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; } } device->drop(); return 0; }
/** Returns the current dt, which guarantees a limited frame rate. If dt is * too low (the frame rate too high), the process will sleep to reach the * maxium frame rate. */ float MainLoop::getLimitedDt() { float dt = 0; // If we are doing a replay, use the dt from the history file if (World::getWorld() && history->replayHistory() ) { dt = history->updateReplayAndGetDT(); return dt; } // In profile mode without graphics, run with a fixed dt of 1/60 if ((ProfileWorld::isProfileMode() && ProfileWorld::isNoGraphics()) || UserConfigParams::m_arena_ai_stats) { return 1.0f/60.0f; } IrrlichtDevice* device = irr_driver->getDevice(); m_prev_time = m_curr_time; while( 1 ) { m_curr_time = device->getTimer()->getRealTime(); dt = (float)(m_curr_time - m_prev_time); const World* const world = World::getWorld(); if (UserConfigParams::m_fps_debug && world) { const LinearWorld *lw = dynamic_cast<const LinearWorld*>(world); if (lw) { Log::verbose("fps", "time %f distance %f dt %f fps %f", lw->getTime(), lw->getDistanceDownTrackForKart(0), dt*0.001f, 1000.0f / dt); } else { Log::verbose("fps", "time %f dt %f fps %f", world->getTime(), dt*0.001f, 1000.0f / dt); } } // Don't allow the game to run slower than a certain amount. // when the computer can't keep it up, slow down the shown time instead // But this can not be done in networking, otherwise the game time on // client and server will not be in synch anymore if(!NetworkConfig::get()->isNetworking()) { static const float max_elapsed_time = 3.0f*1.0f / 60.0f*1000.0f; /* time 3 internal substeps take */ if (dt > max_elapsed_time) dt = max_elapsed_time; } // Throttle fps if more than maximum, which can reduce // the noise the fan on a graphics card makes. // When in menus, reduce FPS much, it's not necessary to push to the maximum for plain menus const int max_fps = (StateManager::get()->throttleFPS() ? 30 : UserConfigParams::m_max_fps); const int current_fps = (int)(1000.0f/dt); if (m_throttle_fps && current_fps > max_fps && !ProfileWorld::isProfileMode()) { int wait_time = 1000/max_fps - 1000/current_fps; if(wait_time < 1) wait_time = 1; PROFILER_PUSH_CPU_MARKER("Throttle framerate", 0, 0, 0); StkTime::sleep(wait_time); PROFILER_POP_CPU_MARKER(); } else break; } dt *= 0.001f; return dt; } // getLimitedDt
/* At first, we let the user select the driver type, then start up the engine, set a caption, and get a pointer to the video driver. */ int main() { // create device IrrlichtDevice *device = createDevice(video::EDT_OPENGL, core::dimension2d<u32>(512, 384)); if (device == 0) return 1; // could not create selected driver. device->setWindowCaption(L"Irrlicht Engine - 2D Graphics Demo"); video::IVideoDriver* driver = device->getVideoDriver(); /* All 2d graphics in this example are put together into one texture, 2ddemo.png. Because we want to draw colorkey based sprites, we need to load this texture and tell the engine, which part of it should be transparent based on a colorkey. In this example, we don't tell it the color directly, we just say "Hey Irrlicht Engine, you'll find the color I want at position (0,0) on the texture.". Instead, it would be also possible to call driver->makeColorKeyTexture(images, video::SColor(0,0,0,0)), to make e.g. all black pixels transparent. Please note that makeColorKeyTexture just creates an alpha channel based on the color. */ video::ITexture* images = driver->getTexture("../../lib/irr/media/2ddemo.png"); driver->makeColorKeyTexture(images, core::position2d<s32>(0,0)); /* To be able to draw some text with two different fonts, we first load them. Ok, we load just one. As the first font we just use the default font which is built into the engine. Also, we define two rectangles which specify the position of the images of the red imps (little flying creatures) in the texture. */ gui::IGUIFont* font = device->getGUIEnvironment()->getBuiltInFont(); gui::IGUIFont* font2 = device->getGUIEnvironment()->getFont("../../lib/irr/media/fonthaettenschweiler.bmp"); core::rect<s32> imp1(349,15,385,78); core::rect<s32> imp2(387,15,423,78); /* Prepare a nicely filtering 2d render mode for special cases. */ driver->getMaterial2D().TextureLayer[0].BilinearFilter=true; driver->getMaterial2D().AntiAliasing=video::EAAM_FULL_BASIC; /* Everything is prepared, now we can draw everything in the draw loop, between the begin scene and end scene calls. In this example, we are just doing 2d graphics, but it would be no problem to mix them with 3d graphics. Just try it out, and draw some 3d vertices or set up a scene with the scene manager and draw it. */ while(device->run() && driver) { if (device->isWindowActive()) { u32 time = device->getTimer()->getTime(); driver->beginScene(true, true, video::SColor(255,120,102,136)); /* First, we draw 3 sprites, using the alpha channel we created with makeColorKeyTexture. The last parameter specifies that the drawing method should use this alpha channel. The last-but-one parameter specifies a color, with which the sprite should be colored. (255,255,255,255) is full white, so the sprite will look like the original. The third sprite is drawn with the red channel modulated based on the time. */ // draw fire & dragons background world driver->draw2DImage(images, core::position2d<s32>(50,50), core::rect<s32>(0,0,342,224), 0, video::SColor(255,255,255,255), true); // draw flying imp driver->draw2DImage(images, core::position2d<s32>(164,125), (time/500 % 2) ? imp1 : imp2, 0, video::SColor(255,255,255,255), true); // draw second flying imp with colorcylce driver->draw2DImage(images, core::position2d<s32>(270,105), (time/500 % 2) ? imp1 : imp2, 0, video::SColor(255,(time) % 255,255,255), true); /* Drawing text is really simple. The code should be self explanatory. */ // draw some text if (font) font->draw(L"This demo shows that Irrlicht is also capable of drawing 2D graphics.", core::rect<s32>(130,10,300,50), video::SColor(255,255,255,255)); // draw some other text if (font2) font2->draw(L"Also mixing with 3d graphics is possible.", core::rect<s32>(130,20,300,60), video::SColor(255,time % 255,time % 255,255)); /* Next, we draw the Irrlicht Engine logo (without using a color or an alpha channel). Since we slightly scale the image we use the prepared filter mode. */ driver->enableMaterial2D(); driver->draw2DImage(images, core::rect<s32>(10,10,108,48), core::rect<s32>(354,87,442,118)); driver->enableMaterial2D(false); /* Finally draw a half-transparent rect under the mouse cursor. */ core::position2d<s32> m = device->getCursorControl()->getPosition(); driver->draw2DRectangle(video::SColor(100,255,255,255), core::rect<s32>(m.X-20, m.Y-20, m.X+20, m.Y+20)); driver->endScene(); } } device->drop(); return 0; }
int main() { Input input; IrrlichtDevice *device = createDevice(video::EDT_DIRECT3D9, dimension2d<u32>(800, 600), 16, false, true, false, &input); device->setWindowCaption(L"Seas of Gold"); IVideoDriver* driver = device->getVideoDriver(); ISceneManager* smgr = device->getSceneManager(); IGUIEnvironment* guienv = device->getGUIEnvironment(); E_DRIVER_TYPE driverType = driverChoiceConsole(); EffectHandler *effect = new EffectHandler(device, driver->getScreenSize(), false, true); E_FILTER_TYPE filterType = (E_FILTER_TYPE)core::clamp<u32>((u32)3 - '1', 0, 4); MapID currentMap; int skyR = 30, skyG = 30, skyB = 70; int timer = 0; SColor sky = SColor(255, skyR, skyG, skyB); float plPos_x = 0.0f, plPos_y = 0.0f, plPos_z = 0.0f; bool updateCam = true; bool menu1 = false; int state = Main; int frameCount = 0; LoadMap loadMap; Player player; Interface playerInterface(driver); ITriangleSelector* selector = 0; ISceneNodeAnimator* anim = 0; Vendor southVendor; Vendor eastVendor; Vendor northVendor; //InitializeVendors(northVendor, southVendor, eastVendor, itemD); //ItemDatabase* itemD = new ItemDatabase; ItemDatabase itemD; itemD.Initialize(); //initialize player's inventory player.AddGold(1000); player.getInventory()->addItem(itemD.getItem(bronzeOre), 50); player.getInventory()->addItem(itemD.getItem(ironOre), 50); player.getInventory()->addItem(itemD.getItem(goldOre), 50); //initialize south vendor's inventory southVendor.getInventory()->addItem(itemD.getItem(bronzeOre), 100); southVendor.getInventory()->addItem(itemD.getItem(coalOre), 100); southVendor.getInventory()->addItem(itemD.getItem(supplies), 1000); //initialize north vendor's inventory northVendor.getInventory()->addItem(itemD.getItem(obsidianOre), 50); northVendor.getInventory()->addItem(itemD.getItem(supplies), 1000); //initialize south vendor's inventory eastVendor.getInventory()->addItem(itemD.getItem(goldOre), 100); eastVendor.getInventory()->addItem(itemD.getItem(ironOre), 100); eastVendor.getInventory()->addItem(itemD.getItem(supplies), 1000); //Item item(0, "bronzeOre", "Sprites/ore_Bronze.png"); //Item item2 = item; //Item* item2 = itemD.getItem(3); //inventory.addItem(&item, 2); //inventory.addItem(&item, 2); //inventory.addItem(item2, 2); //int test = 0; // Load the map scene //loadMap.Load(smgr, device, Map_Africa); //loadMap.Load(smgr, device, Map_India); //loadMap.Load(smgr, device, selector, plyrNode, anim, Map_England); IAnimatedMeshSceneNode* plyrNode = player.loadPlayerNode(device, smgr); //plyrNode->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(plyrNode->isDebugDataVisible() ^ scene::EDS_BBOX)); ICameraSceneNode* camera = smgr->addCameraSceneNode(0, plyrNode->getPosition() + vector3df(0, 2, 2), vector3df(0, 0, 100)); loadMap.Load(smgr, device, selector, plyrNode, anim, driver, Map_Africa); currentMap = Map_Africa; //loadMap.setCollisions(smgr, selector, plyrNode, anim); if (loadMap.CollNode) { selector = smgr->createOctreeTriangleSelector(loadMap.CollNode->getMesh(), loadMap.CollNode, 32); for (int i = 0; i < loadMap.CollNode->getMaterialCount(); i++) { loadMap.CollNode->getMaterial(i).NormalizeNormals = true; } loadMap.CollNode->setTriangleSelector(selector); } if (selector) { anim = smgr->createCollisionResponseAnimator(selector, plyrNode, vector3df(0.6f, 0.75f, 0.4f), core::vector3df(0.0f, -0.05f, 0.0f), core::vector3df(0.0f, -0.725f, 0.0f)); plyrNode->addAnimator(anim); } ISceneCollisionManager* collMan = smgr->getSceneCollisionManager(); ////////////// The Sun //////////// ILightSceneNode *sun_node; SLight sun_data; ISceneNode *sun_billboard; float sun_angle = 0; video::SColorf Diffuse_Night = video::SColorf(0.0f, 0.0f, 0.0f, 1.0f); video::SColorf Diffuse_Day = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f); sun_node = smgr->addLightSceneNode(); sun_data.Direction = vector3df(0, 0, 0); sun_data.Type = video::ELT_DIRECTIONAL; sun_data.AmbientColor = video::SColorf(0.1f, 0.1f, 0.1f, 1); sun_data.SpecularColor = video::SColorf(0, 0, 0, 0); sun_data.DiffuseColor = Diffuse_Day; sun_data.CastShadows = true; sun_node->setLightData(sun_data); sun_node->setPosition(vector3df(0, 0, 0)); sun_node->setRotation(vector3df(0, 0, 0)); sun_billboard = smgr->addBillboardSceneNode(sun_node, core::dimension2d<f32>(60, 60)); if (sun_billboard) { sun_billboard->setPosition(vector3df(0, 0, -100)); sun_billboard->setMaterialFlag(video::EMF_LIGHTING, false); sun_billboard->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); sun_billboard->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); sun_billboard->setMaterialTexture(0, driver->getTexture("Assets/particlewhite.bmp")); } /////////// End //////////// //------- candleLight -----// ILightSceneNode *candleLight = smgr->addLightSceneNode(); SLight candleLight_data; candleLight_data.Type = video::ELT_POINT; candleLight_data.DiffuseColor = SColorf(1.0f, 0.546f, 0.016f, 1.0f); candleLight_data.SpecularColor = video::SColorf(0, 0, 0, 0); candleLight->setPosition(vector3df(2.43467f, 1.55795f, -3.94657)); candleLight_data.Radius = 1.5f; candleLight->setLightData(candleLight_data); //------- end -----// //// Make the player //player.AddGold(1000); //player.SetCurrentPort(eMapDest::South); //Item* itemCi = new Item("Iron Ore", 1); //player.getItems()->addItem(itemCi); //Item* itemCb = new Item("Bronze Ore", 1); //player.getItems()->addItem(itemCb); //Vendor vN; //Item* itemG = new Item("Gold Ore", 1000); //vN.getItems()->addItem(itemG); //Vendor vS; //Item* itemI = new Item("Iron Ore", 1000); //vS.getItems()->addItem(itemI); //Vendor vE; //Item* itemB = new Item("Bronze Ore", 1000); //vE.getItems()->addItem(itemB); //Vendor northVendor //delete &itemD; int test99 = 0; // Make the menus MainMenu mainMenu(device, driver); MapMenu mapMenu(device, driver); mapMenu.SetPlayer(&player); TradeMenu tradeMenu; tradeMenu.Initialize(device, driver, &player, &southVendor); //TradeMenu tradeMenu(device, driver); //tradeMenu.SetPlayer(&player); //tradeMenu.SetVendor(&vS); // CraftingMenu craftMenu(device, driver, &player, itemD); //craftMenu.SetPlayer(&player); ////////////////////////////////////////////////////////////////////////// // Initialize timer to compute elapsed time between frames ////////////////////////////////////////////////////////////////////////// __int64 cntsPerSec = 0; QueryPerformanceFrequency((LARGE_INTEGER*)&cntsPerSec); float secsPerCnt = 1.0f / (float)cntsPerSec; __int64 prevTimeStamp = 0; QueryPerformanceCounter((LARGE_INTEGER*)&prevTimeStamp); while (device->run()) { //for scaling animation by time, not by frame __int64 currTimeStamp = 0; QueryPerformanceCounter((LARGE_INTEGER*)&currTimeStamp); float dt = (currTimeStamp - prevTimeStamp) * secsPerCnt; sun_node->setRotation(vector3df(sun_angle, 0.0f, 0.0f)); sun_angle += dt; frameCount += 1; if ((sun_angle > 0 && sun_angle < 109) || (sun_angle>350)) { timer++; if (timer > 10) { if (skyR < 100) skyR += 1; if (skyG < 100) skyG += 1; if (skyB < 140) skyB += 1; timer = 0; } } if (sun_angle > 170 && sun_angle < 330) { timer++; if (timer > 10) { if (skyR > 0) skyR -= 1; if (skyG > 0) skyG -= 1; if (skyB > 40) skyB -= 1; timer = 0; } } player.updatePlayer(plyrNode, dt, collMan, selector); playerInterface.update(plyrNode, loadMap, driver, device, input, updateCam, state); switch (state) { case Map: { int out = mapMenu.Update(&input, frameCount); switch (out) { case eMapDest::Exit: { state = None; break; } case eMapDest::East: { state = None; //Item* itemB = new Item("Bronze Ore", 1000); //vE.getItems()->addItem(itemB); tradeMenu.SetVendor(&eastVendor); loadMap.Load(smgr, device, selector, plyrNode, anim, driver, Map_India); currentMap = Map_India; if (loadMap.CollNode) { selector = smgr->createOctreeTriangleSelector(loadMap.CollNode->getMesh(), loadMap.CollNode, 32); for (int i = 0; i < loadMap.CollNode->getMaterialCount(); i++) { loadMap.CollNode->getMaterial(i).NormalizeNormals = true; } loadMap.CollNode->setTriangleSelector(selector); } if (selector) { anim = smgr->createCollisionResponseAnimator(selector, plyrNode, vector3df(0.6f, 0.75f, 0.4f), core::vector3df(0.0f, -0.05f, 0.0f), core::vector3df(0.0f, -0.725f, 0.0f)); plyrNode->addAnimator(anim); } collMan = smgr->getSceneCollisionManager(); break; } case eMapDest::North: { state = None; //Item *itemG = new Item("Gold Ore", 1000); //vN.getItems()->addItem(itemG); //tradeMenu.SetVendor(&vN); tradeMenu.SetVendor(&northVendor); loadMap.Load(smgr, device, selector, plyrNode, anim, driver, Map_England); currentMap = Map_England; if (loadMap.CollNode) { selector = smgr->createOctreeTriangleSelector(loadMap.CollNode->getMesh(), loadMap.CollNode, 32); for (int i = 0; i < loadMap.CollNode->getMaterialCount(); i++) { loadMap.CollNode->getMaterial(i).NormalizeNormals = true; } loadMap.CollNode->setTriangleSelector(selector); } if (selector) { anim = smgr->createCollisionResponseAnimator(selector, plyrNode, vector3df(0.6f, 0.75f, 0.4f), core::vector3df(0.0f, -0.05f, 0.0f), core::vector3df(0.0f, -0.725f, 0.0f)); plyrNode->addAnimator(anim); } collMan = smgr->getSceneCollisionManager(); break; } case eMapDest::South: { state = None; //Item *itemI = new Item("Iron Ore", 1000); //vS.getItems()->addItem(itemI); //tradeMenu.SetVendor(&vS); tradeMenu.SetVendor(&southVendor); loadMap.Load(smgr, device, selector, plyrNode, anim, driver, Map_Africa); currentMap = Map_Africa; if (loadMap.CollNode) { selector = smgr->createOctreeTriangleSelector(loadMap.CollNode->getMesh(), loadMap.CollNode, 32); for (int i = 0; i < loadMap.CollNode->getMaterialCount(); i++) { loadMap.CollNode->getMaterial(i).NormalizeNormals = true; } loadMap.CollNode->setTriangleSelector(selector); } if (selector) { anim = smgr->createCollisionResponseAnimator(selector, plyrNode, vector3df(0.6f, 0.75f, 0.4f), core::vector3df(0.0f, -0.05f, 0.0f), core::vector3df(0.0f, -0.725f, 0.0f)); plyrNode->addAnimator(anim); } collMan = smgr->getSceneCollisionManager(); break; } default: break; } break; } case Trade: { bool out = false; out = tradeMenu.Update(&input, frameCount, device, currentMap); if (out) state = None; break; } case Main: { int out = mainMenu.Update(&input, frameCount); switch (out) { case MSstart: { state = None; break; } case MSexit: { device->closeDevice(); //return 0; break; } default: break; } break; } case Craft: { bool out = craftMenu.Update(&input, frameCount, device); if (out) state = None; break; } default: // Do nothing break; } if (updateCam) moveCameraControl(plyrNode, device, camera); //////////////////////////////////////////////////////// if (sun_angle > 360) sun_angle = 0; if (sun_angle < 180) sun_data.DiffuseColor = Diffuse_Day; else sun_data.DiffuseColor = Diffuse_Night; sun_node->setLightData(sun_data); sky.setRed(skyR); sky.setGreen(skyG); sky.setBlue(skyB); driver->beginScene(true, true, sky); smgr->drawAll(); playerInterface.render(driver, state); // Draw the menu switch (state) { case Map: { mapMenu.Draw(driver, device); break; } case Trade: { tradeMenu.Render(driver, device); break; } case Main: { mainMenu.Draw(driver); break; } case Craft: { craftMenu.Draw(driver); break; } default: // Do nothing break; } driver->endScene(); // Update the prev time stamp to current prevTimeStamp = currTimeStamp; } device->drop(); return 0; }
/** Returns the current real time, which might not be 0 at start of the * application. Value in msec. */ unsigned int getRealTime() {return m_device->getTimer()->getRealTime(); }
bool testTransparentVertexAlphaMore(E_DRIVER_TYPE driverType) { IrrlichtDevice *device = createDevice(driverType, dimension2d<u32>(160, 120)); if (!device) return true; IVideoDriver* driver = device->getVideoDriver(); ISceneManager* smgr = device->getSceneManager(); if (driver->getColorFormat() != video::ECF_A8R8G8B8) { device->closeDevice(); device->run(); device->drop(); return true; } stabilizeScreenBackground(driver); logTestString("Testing driver %ls\n", driver->getName()); IAnimatedMesh* mesh = smgr->getMesh("../media/sydney.md2"); IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh ); IMeshSceneNode* cube = smgr->addCubeSceneNode(10.0f,0,-1,vector3df(-5,3,-15)); if (node) { node->setMaterialFlag(EMF_LIGHTING, false); node->setFrameLoop(0, 310); node->setMaterialTexture( 0, driver->getTexture("../media/sydney.bmp") ); } if (cube) { cube->getMaterial(0).MaterialType = EMT_TRANSPARENT_VERTEX_ALPHA; cube->setMaterialTexture(0, driver->getTexture("../media/wall.bmp")); cube->setMaterialFlag(EMF_LIGHTING, false); smgr->getMeshManipulator()->setVertexColorAlpha(cube->getMesh(),128); } // second cube without texture cube = smgr->addCubeSceneNode(10.0f,0,-1,vector3df(5,3,-15)); if (cube) { cube->getMaterial(0).MaterialType = EMT_TRANSPARENT_VERTEX_ALPHA; cube->setMaterialFlag(EMF_LIGHTING, false); smgr->getMeshManipulator()->setVertexColorAlpha(cube->getMesh(),128); } smgr->addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0)); driver->beginScene(true, true, SColor(0,200,200,200)); smgr->drawAll(); driver->endScene(); bool result = takeScreenshotAndCompareAgainstReference(driver, "-transparentVertexAlphaChannelMore.png", 99.18f); device->closeDevice(); device->run(); device->drop(); return result; }
int main() { dimension2d<s32> Res(600,400); IrrlichtDevice* device = createDevice(EDT_OPENGL, Res, 16, false); if (!device) return 0; IVideoDriver* driver = device->getVideoDriver(); ISceneManager* smgr = device->getSceneManager(); device->setWindowCaption(L"progress bars"); // add test bars CGUIBar* healthBar[4]; // the 1st bar will go from 0 to 255 u8 a=0; healthBar[0] = new CGUIBar(20,40, 200,60, a, driver); // while the other will go from 255 to 0 // u8 b = 255; // healthBar[1] = new CGUIBar(20,80, 200,100, b, driver); // and two dummy bars respectively initialized to value 120 and 200 // healthBar[2] = new CGUIBar(20,120, 200,140, 120, driver); // healthBar[3] = new CGUIBar(20,160, 200,180, 200, driver); u32 now=0, then=0; while(device->run()) { if (device->isWindowActive()) { now = device->getTimer()->getTime(); if (then < now) { driver->beginScene(true, true, 0); ////smgr->drawAll(); no scene here // increase first bar ////a = healthBar[0]->getValue() + 1; a++; if (a >= 255) break; healthBar[0]->setValue(a); // decrease second bar // b--; // if (b == 0) break; // healthBar[1]->setValue(b); // for (u8 n=0; n<4; n++) healthBar[0]->draw(); driver->endScene(); then = now + 30; } device->sleep(10,0); } } delete healthBar[0]; delete healthBar[1]; device->closeDevice(); printf("Press any key to exit ..."); getchar(); return 0; }
/* The start of the main function starts like in most other example. We ask the user for the desired renderer and start it up. This time with the advanced parameter handling. */ int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // create device with full flexibility over creation parameters // you can add more parameters if desired, check irr::SIrrlichtCreationParameters irr::SIrrlichtCreationParameters params; params.DriverType=driverType; params.WindowSize=core::dimension2d<u32>(640, 480); IrrlichtDevice* device = createDeviceEx(params); if (device == 0) return 1; // could not create selected driver. /* First, we add standard stuff to the scene: A nice irrlicht engine logo, a small help text, a user controlled camera, and we disable the mouse cursor. */ video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* env = device->getGUIEnvironment(); driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true); // add irrlicht logo env->addImage(driver->getTexture("../../media/irrlichtlogo2.png"), core::position2d<s32>(10,10)); //set other font env->getSkin()->setFont(env->getFont("../../media/fontlucida.png")); // add some help text env->addStaticText( L"Press 'W' to change wireframe mode\nPress 'D' to toggle detail map\nPress 'S' to toggle skybox/skydome", core::rect<s32>(10,421,250,475), true, true, 0, -1, true); // add camera scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(0,100.0f,1.2f); camera->setPosition(core::vector3df(2700*2,255*2,2600*2)); camera->setTarget(core::vector3df(2397*2,343*2,2700*2)); camera->setFarValue(42000.0f); // disable mouse cursor device->getCursorControl()->setVisible(false); /* Here comes the terrain renderer scene node: We add it just like any other scene node to the scene using ISceneManager::addTerrainSceneNode(). The only parameter we use is a file name to the heightmap we use. A heightmap is simply a gray scale texture. The terrain renderer loads it and creates the 3D terrain from it. To make the terrain look more big, we change the scale factor of it to (40, 4.4, 40). Because we don't have any dynamic lights in the scene, we switch off the lighting, and we set the file terrain-texture.jpg as texture for the terrain and detailmap3.jpg as second texture, called detail map. At last, we set the scale values for the texture: The first texture will be repeated only one time over the whole terrain, and the second one (detail map) 20 times. */ // add terrain scene node scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode( "../../media/terrain-heightmap.bmp", 0, // parent node -1, // node id core::vector3df(0.f, 0.f, 0.f), // position core::vector3df(0.f, 0.f, 0.f), // rotation core::vector3df(40.f, 4.4f, 40.f), // scale video::SColor ( 255, 255, 255, 255 ), // vertexColor 5, // maxLOD scene::ETPS_17, // patchSize 4 // smoothFactor ); terrain->setMaterialFlag(video::EMF_LIGHTING, false); terrain->setMaterialTexture(0, driver->getTexture("../../media/terrain-texture.jpg")); terrain->setMaterialTexture(1, driver->getTexture("../../media/detailmap3.jpg")); terrain->setMaterialType(video::EMT_DETAIL_MAP); terrain->scaleTexture(1.0f, 20.0f); /* To be able to do collision with the terrain, we create a triangle selector. If you want to know what triangle selectors do, just take a look into the collision tutorial. The terrain triangle selector works together with the terrain. To demonstrate this, we create a collision response animator and attach it to the camera, so that the camera will not be able to fly through the terrain. */ // create triangle selector for the terrain scene::ITriangleSelector* selector = smgr->createTerrainTriangleSelector(terrain, 0); terrain->setTriangleSelector(selector); // create collision response animator and attach it to the camera scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator( selector, camera, core::vector3df(60,100,60), core::vector3df(0,0,0), core::vector3df(0,50,0)); selector->drop(); camera->addAnimator(anim); anim->drop(); /* To make the user be able to switch between normal and wireframe mode, we create an instance of the event receiver from above and let Irrlicht know about it. In addition, we add the skybox which we already used in lots of Irrlicht examples and a skydome, which is shown mutually exclusive with the skybox by pressing 'S'. */ // create skybox and skydome driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); scene::ISceneNode* skybox=smgr->addSkyBoxSceneNode( driver->getTexture("../../media/irrlicht2_up.jpg"), driver->getTexture("../../media/irrlicht2_dn.jpg"), driver->getTexture("../../media/irrlicht2_lf.jpg"), driver->getTexture("../../media/irrlicht2_rt.jpg"), driver->getTexture("../../media/irrlicht2_ft.jpg"), driver->getTexture("../../media/irrlicht2_bk.jpg")); scene::ISceneNode* skydome=smgr->addSkyDomeSceneNode(driver->getTexture("../../media/skydome.jpg"),16,8,0.95f,2.0f); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true); // create event receiver MyEventReceiver receiver(terrain, skybox, skydome); device->setEventReceiver(&receiver); /* That's it, draw everything. */ int lastFPS = -1; while(device->run()) if (device->isWindowActive()) { driver->beginScene(true, true, 0 ); smgr->drawAll(); env->drawAll(); driver->endScene(); // display frames per second in window title int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Terrain Renderer - Irrlicht Engine ["; str += driver->getName(); str += "] FPS:"; str += fps; // Also print terrain height of current camera position // We can use camera position because terrain is located at coordinate origin str += " Height: "; str += terrain->getHeight(camera->getAbsolutePosition().X, camera->getAbsolutePosition().Z); device->setWindowCaption(str.c_str()); lastFPS = fps; } } device->drop(); return 0; }
int main(int argc, char **argv) { BSPdungeon dun(50,50,5); IrrlichtDevice *device =createDevice( video::EDT_OPENGL, dimension2d<u32>(1280,720), 16,false, false, false, 0); if (!device) return 1; device->setWindowCaption(L"Pangolin Kwest"); IVideoDriver* driver = device->getVideoDriver(); ISceneManager* smgr = device->getSceneManager(); IGUIEnvironment* guienv = device->getGUIEnvironment(); smgr->setAmbientLight(video::SColorf(0.1,0.1,0.1,1)); ILightSceneNode* mylight1 = smgr->addLightSceneNode( 0, core::vector3df(00,00,00), video::SColorf(0.3f,0.3f,0.3f), 30.0f, 1 ); //IGUIFont* myfont=guienv->getFont("./myfont.xml"); //if(myfont==0)exit(93); //guienv->addMessageBox(L"Alertz!",L"You pangolin are been createrized. You totalleh ready to bash monstaz etc.!"); mylight1->enableCastShadow(true); //guienv->addStaticText(L"Pangolin Kwest 3D",rect<s32>(10,10,260,22), true); //------------------------------------------- int x,y,z; for(x=0;x<50;x++){ for(y=0;y<50;y++){ if(dun.map[x][y]==NIL){ for(z=0;z<3;z++){ ISceneNode* cueb=smgr->addCubeSceneNode(10); cueb->setMaterialFlag(EMF_LIGHTING, true); cueb->setMaterialTexture( 0, driver->getTexture("media/stdwall.jpg") ); // cueb->getMaterial(0).getTextureMatrix(0).setTextureTranslate(0.25,0.5); // cueb->getMaterial(0).getTextureMatrix(0).setTextureScale(0.0625,0.0625); cueb->setPosition(vector3df(x*10,z*10,y*10)); } } // ISceneNode* cueb=smgr->addCubeSceneNode(10); // cueb->setMaterialFlag(EMF_LIGHTING, true); // cueb->setMaterialTexture( 0, driver->getTexture("media/stdfloor.jpg") ); // cueb->setPosition(vector3df(x*10,-10,y*10)); ISceneNode* cueb=smgr->addCubeSceneNode(10); cueb->setMaterialFlag(EMF_LIGHTING, true); cueb->setMaterialTexture( 0, driver->getTexture("media/stdup.jpg") ); cueb->setPosition(vector3df(x*10,30,y*10)); } } ISceneNode* cueb=smgr->addCubeSceneNode(500); cueb->setMaterialFlag(EMF_LIGHTING, true); cueb->setMaterialTexture( 0, driver->getTexture("media/stdfloor.jpg") ); cueb->setPosition(vector3df(250,-255,250)); //cueb->getMaterial(0).getTextureMatrix(0).setTextureTranslate(0.25,0.5); cueb->getMaterial(0).getTextureMatrix(0).setTextureScale(50,50); //cueb->setScale(vector3df(0,-5,0)); //cueb->addshadowVolumeSceneNode(); //------------------------------------------- int lastFPS; //smgr->addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0)); ICameraSceneNode* mycam; mycam=smgr->addCameraSceneNodeFPS(0,100.0f,0.025f); mycam->setFOV(45); mylight1->setParent(mycam); while(device->run()) { //mylight1->setPosition(); //mylight1-> driver->beginScene(true, true, SColor(255,100,101,140)); smgr->drawAll(); guienv->drawAll(); driver->endScene(); int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Pangolin Kwest 3D ["; str += driver->getName(); str += "] FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; } } device->drop(); return 0; }
/* This is the main method. We can use void main() on every platform. On Windows platforms, we could also use the WinMain method if we would want to get rid of the console window, which pops up when starting a program with main(), but to keep this example simple, we use main(). */ int main(int argc, char** argv) { /* The most important function of the engine is the 'createDevice' function. The Irrlicht Device can be created with it, which is the root object for doing everything with the engine. createDevice() has 7 paramters: deviceType: Type of the device. This can currently be the Null-device, the Software device, DirectX8, DirectX9, or OpenGL. In this example we use EDT_SOFTWARE, but to try out, you might want to change it to EDT_NULL, EDT_DIRECTX8 , EDT_DIRECTX9, or EDT_OPENGL. windowSize: Size of the Window or FullscreenMode to be created. In this example we use 640x480. bits: Amount of bits per pixel when in fullscreen mode. This should be 16 or 32. This parameter is ignored when running in windowed mode. fullscreen: Specifies if we want the device to run in fullscreen mode or not. stencilbuffer: Specifies if we want to use the stencil buffer for drawing shadows. vsync: Specifies if we want to have vsync enabled, this is only useful in fullscreen mode. eventReceiver: An object to receive events. We do not want to use this parameter here, and set it to 0. */ IrrlichtDevice *device = createDevice(EDT_SOFTWARE, dimension2d<s32>(640, 480), 16, false, false, false, 0); /* Set the caption of the window to some nice text. Note that there is a 'L' in front of the string. The Irrlicht Engine uses wide character strings when displaying text. */ device->setWindowCaption(L"Hello World! - Irrlicht Engine Demo"); /* Get a pointer to the video driver, the SceneManager and the graphical user interface environment, so that we do not always have to write device->getVideoDriver(), device->getSceneManager() and device->getGUIEnvironment(). */ IVideoDriver* driver = device->getVideoDriver(); ISceneManager* smgr = device->getSceneManager(); IGUIEnvironment* guienv = device->getGUIEnvironment(); /* We add a hello world label to the window, using the GUI environment. */ guienv->addStaticText(L"Hello World! This is the Irrlicht Software renderer!", rect<int>(10,10,200,22), true); /* To display something interesting, we load a Quake 2 model and display it. We only have to get the Mesh from the Scene Manager (getMesh()) and add a SceneNode to display the mesh. (addAnimatedMeshSceneNode()). Instead of writing the filename sydney.md2, it would also be possible to load a Maya object file (.obj), a complete Quake3 map (.bsp) or a Milshape file (.ms3d). By the way, that cool Quake 2 model called sydney was modelled by Brian Collins. */ IAnimatedMesh* mesh = smgr->getMesh("../../media/sydney.md2"); IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh ); /* To let the mesh look a little bit nicer, we change its material a little bit: We disable lighting because we do not have a dynamic light in here, and the mesh would be totally black. Then we set the frame loop, so that the animation is looped between the frames 0 and 310. And at last, we apply a texture to the mesh. Without it the mesh would be drawn using only a color. */ if (node) { node->setMaterialFlag(EMF_LIGHTING, false); node->setFrameLoop(0, 310); node->setMaterialTexture( 0, driver->getTexture("../../media/sydney.bmp") ); } /* To look at the mesh, we place a camera into 3d space at the position (0, 30, -40). The camera looks from there to (0,5,0). */ smgr->addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0)); /* Ok, now we have set up the scene, lets draw everything: We run the device in a while() loop, until the device does not want to run any more. This would be when the user closed the window or pressed ALT+F4 in windows. */ while(device->run()) { /* Anything can be drawn between a beginScene() and an endScene() call. The beginScene clears the screen with a color and also the depth buffer if wanted. Then we let the Scene Manager and the GUI Environment draw their content. With the endScene() call everything is presented on the screen. */ driver->beginScene(true, true, SColor(0,200,200,200)); smgr->drawAll(); guienv->drawAll(); driver->endScene(); } /* After we are finished, we have to delete the Irrlicht Device created before with createDevice(). In the Irrlicht Engine, you will have to delete all objects you created with a method or function which starts with 'create'. The object is simply deleted by calling ->drop(). See the documentation at http://irrlicht.sourceforge.net//docu/classirr_1_1IUnknown.html#a3 for more information. */ device->drop(); return 0; }
/** Run the actual main loop. * The sequnce in which various parts of STK are updated is: * - Determine next time step size (`getLimitedDt`). This takes maximum fps * into account (i.e. sleep if the fps would be too high), and will actually * slow down the in-game clock if the fps are too low (if more than 3/60 of * a second have passed, more than 3 physics time steps would be needed, * and physics do at most 3 time steps). * - if a race is taking place (i.e. not only a menu being shown), call * `updateRace()`, which is a thin wrapper around a call to * `World::updateWorld()`: * - Update history manager (which will either set the kart position and/or * controls when replaying, or store the current info for a replay). * This is mostly for debugging only (though available even in release * mode). * - Updates Replays - either storing data when not replaying, or * updating kart positions/control when replaying). * - Calls `WorldStatus::update()`, which updates the race state (e.g. * go from 'ready' to 'set' etc), and clock. * - Updates the physics (`Physics::update()`). This will simulate all * physical objects for the specified time with bullet. * - Updates all karts (`Kart::update()`). Obviously the update function * does a lot more than what is described here, this is only supposed to * be a _very_ high level overview: * - Updates its rewinder (to store potentially changed controls * as events) in `KartRewinder::update()`. * - Calls `Moveable::update()`, which takes the new position from * the physics and saves it (and computes dependent values, like * heading, local velocity). * - Updates its controller. This is either: * - an AI using `SkiddingController::update()` (which then will * compute the new controls), or * - a player controller using `PlayerController::update()`, which will * handle smooth steering (in case of digital input devices steering * is adjusted a bit over time to avoid an instant change from all * left to all right). Input events will be handled when updating * the irrlicht driver later at the end of the main loop. * - Updates kart animation (like rescue, ...) if one is shown atm. * - Update attachments. * - update physics, i.e. taking the current steering and updating * the bullet raycast vehicle with that data. The settings are actually * only used in the next frame when the physics are updated. * - Updates all cameras via `Camera::update()`. The camera position and * rotation is adjusted according to the position etc of the kart (and * special circumstances like rescue, falling). * - Updates all projectiles using the projectile manager. Some of the * projectiles are mostly handled by the physics (e.g. a cake will mainly * check if it's out of bounds), others (like basket ball) do all * their aiming and movement here. * - Updates the rewind manager to store rewind states. * - Updates the music manager. * - Updates the input manager (which only updates internal time, actual * input handling follows late) * - Updates the wiimote manager. This will read the data of all wiimotes * and feed the corresponding events to the irrlicht event system. * - Updates the STK internal gui engine. This updates all widgets, and * e.g. takes care of the rotation of the karts in the KartSelection * screen using the ModelViewWidget. * - Updates STK's irrlicht driver `IrrDriver::update()`: * - Calls Irrlicht's `beginScene()` . * - Renders the scene (several times with different viewport if * split screen is being used) * - Calls `GUIEngine::render()`, which renders all widgets with the * help of Irrlicht's GUIEnvironment (`drawAll()`). This will also * handle all events, i.e. all input is now handled (e.g. steering, * firing etc are all set in the corresponding karts depending on * user input). * - Calls Irrlicht's `endScene()` */ void MainLoop::run() { IrrlichtDevice* device = irr_driver->getDevice(); m_curr_time = device->getTimer()->getRealTime(); while(!m_abort) { PROFILER_PUSH_CPU_MARKER("Main loop", 0xFF, 0x00, 0xF7); m_prev_time = m_curr_time; float dt = getLimitedDt(); if (!m_abort && !ProfileWorld::isNoGraphics()) { // Render the previous frame, and also handle all user input. PROFILER_PUSH_CPU_MARKER("IrrDriver update", 0x00, 0x00, 0x7F); irr_driver->update(dt); PROFILER_POP_CPU_MARKER(); } if (World::getWorld()) // race is active if world exists { PROFILER_PUSH_CPU_MARKER("Update race", 0, 255, 255); updateRace(dt); PROFILER_POP_CPU_MARKER(); } // if race is active // We need to check again because update_race may have requested // the main loop to abort; and it's not a good idea to continue // since the GUI engine is no more to be called then. // Also only do music, input, and graphics update if graphics are // enabled. if (!m_abort && !ProfileWorld::isNoGraphics()) { PROFILER_PUSH_CPU_MARKER("Music/input/GUI", 0x7F, 0x00, 0x00); input_manager->update(dt); #ifdef ENABLE_WIIUSE wiimote_manager->update(); #endif GUIEngine::update(dt); PROFILER_POP_CPU_MARKER(); // Update sfx and music after graphics, so that graphics code // can use as many threads as possible without interfering // with audio PROFILER_PUSH_CPU_MARKER("Music/input/GUI", 0x7F, 0x00, 0x00); SFXManager::get()->update(); PROFILER_POP_CPU_MARKER(); PROFILER_PUSH_CPU_MARKER("Protocol manager update", 0x7F, 0x00, 0x7F); if (STKHost::existHost()) { if (STKHost::get()->requestedShutdown()) STKHost::get()->shutdown(); else ProtocolManager::getInstance()->update(dt); } PROFILER_POP_CPU_MARKER(); PROFILER_PUSH_CPU_MARKER("Database polling update", 0x00, 0x7F, 0x7F); Online::RequestManager::get()->update(dt); PROFILER_POP_CPU_MARKER(); } else if (!m_abort && ProfileWorld::isNoGraphics()) { PROFILER_PUSH_CPU_MARKER("Protocol manager update", 0x7F, 0x00, 0x7F); if(NetworkConfig::get()->isNetworking()) ProtocolManager::getInstance()->update(dt); PROFILER_POP_CPU_MARKER(); PROFILER_PUSH_CPU_MARKER("Database polling update", 0x00, 0x7F, 0x7F); Online::RequestManager::get()->update(dt); PROFILER_POP_CPU_MARKER(); } if (World::getWorld() ) { World::getWorld()->updateTime(dt); } PROFILER_POP_CPU_MARKER(); PROFILER_SYNC_FRAME(); } // while !m_abort } // run
/* Ok, now the main-function: First, we initialize the device, get the SourceManager and VideoDriver, load an animated mesh from .md2 and a map from .pk3. Because that's old stuff, I won't explain every step. Just take care of the maps position. */ int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; //Instance of the EventReceiver MyEventReceiver receiver; //Initialise the engine IrrlichtDevice *device = createDevice(driverType, dimension2du(ResX,ResY), 32, fullScreen, false, false, &receiver); if (!device) return 1; ISceneManager *smgr = device->getSceneManager(); IVideoDriver *driver = device->getVideoDriver(); //Load model IAnimatedMesh *model = smgr->getMesh("../../media/sydney.md2"); if (!model) return 1; IAnimatedMeshSceneNode *model_node = smgr->addAnimatedMeshSceneNode(model); //Load texture if (model_node) { ITexture *texture = driver->getTexture("../../media/sydney.bmp"); model_node->setMaterialTexture(0,texture); model_node->setMD2Animation(scene::EMAT_RUN); //Disable lighting (we've got no light) model_node->setMaterialFlag(EMF_LIGHTING,false); } //Load map device->getFileSystem()->addFileArchive("../../media/map-20kdm2.pk3"); IAnimatedMesh *map = smgr->getMesh("20kdm2.bsp"); if (map) { ISceneNode *map_node = smgr->addOctreeSceneNode(map->getMesh(0)); //Set position map_node->setPosition(vector3df(-850,-220,-850)); } /* Now we create our four cameras. One is looking at the model from the front, one from the top and one from the side. In addition there's a FPS-camera which can be controlled by the user. */ // Create 3 fixed and one user-controlled cameras //Front camera[0] = smgr->addCameraSceneNode(0, vector3df(50,0,0), vector3df(0,0,0)); //Top camera[1] = smgr->addCameraSceneNode(0, vector3df(0,50,0), vector3df(0,0,0)); //Left camera[2] = smgr->addCameraSceneNode(0, vector3df(0,0,50), vector3df(0,0,0)); //User-controlled camera[3] = smgr->addCameraSceneNodeFPS(); // don't start at sydney's position if (camera[3]) camera[3]->setPosition(core::vector3df(-50,0,-50)); /* Create a variable for counting the fps and hide the mouse: */ //Hide mouse device->getCursorControl()->setVisible(false); //We want to count the fps int lastFPS = -1; /* There wasn't much new stuff - till now! Only by defining four cameras, the game won't be splitscreen. To do this you need several steps: - Set the viewport to the whole screen - Begin a new scene (Clear screen) - The following 3 steps are repeated for every viewport in the splitscreen - Set the viewport to the area you wish - Activate the camera which should be "linked" with the viewport - Render all objects - If you have a GUI: - Set the viewport the whole screen - Display the GUI - End scene Sounds a little complicated, but you'll see it isn't: */ while(device->run()) { //Set the viewpoint to the whole screen and begin scene driver->setViewPort(rect<s32>(0,0,ResX,ResY)); driver->beginScene(true,true,SColor(255,100,100,100)); //If SplitScreen is used if (SplitScreen) { //Activate camera1 smgr->setActiveCamera(camera[0]); //Set viewpoint to the first quarter (left top) driver->setViewPort(rect<s32>(0,0,ResX/2,ResY/2)); //Draw scene smgr->drawAll(); //Activate camera2 smgr->setActiveCamera(camera[1]); //Set viewpoint to the second quarter (right top) driver->setViewPort(rect<s32>(ResX/2,0,ResX,ResY/2)); //Draw scene smgr->drawAll(); //Activate camera3 smgr->setActiveCamera(camera[2]); //Set viewpoint to the third quarter (left bottom) driver->setViewPort(rect<s32>(0,ResY/2,ResX/2,ResY)); //Draw scene smgr->drawAll(); //Set viewport the last quarter (right bottom) driver->setViewPort(rect<s32>(ResX/2,ResY/2,ResX,ResY)); } //Activate camera4 smgr->setActiveCamera(camera[3]); //Draw scene smgr->drawAll(); driver->endScene(); /* As you can probably see, the image is rendered for every viewport seperately. That means, that you'll loose much performance. Ok, if you're aksing "How do I have to set the viewport to get this or that screen?", don't panic. It's really easy: In the rect-function you define 4 coordinates: - X-coordinate of the corner left top - Y-coordinate of the corner left top - X-coordinate of the corner right bottom - Y-coordinate of the corner right bottom That means, if you want to split the screen into 2 viewports you would give the following coordinates: - 1st viewport: 0,0,ResX/2,ResY - 2nd viewport: ResX/2,0,ResX,ResY If you didn't fully understand, just play arround with the example to check out what happens. Now we just view the current fps and shut down the engine, when the user wants to: */ //Get and show fps if (driver->getFPS() != lastFPS) { lastFPS = driver->getFPS(); core::stringw tmp = L"Irrlicht SplitScreen-Example (FPS: "; tmp += lastFPS; tmp += ")"; device->setWindowCaption(tmp.c_str()); } } //Delete device device->drop(); return 0; }
int main(int argc, char *argv[]) { int retval = 0; /* Initialization */ log_add_output_maxlev(&main_stderr_log_out, LMT_ACTION); log_add_output_all_levs(&main_dstream_no_stderr_log_out); log_register_thread("main"); /* Parse command line */ // List all allowed options std::map<std::string, ValueSpec> allowed_options; allowed_options.insert(std::make_pair("help", ValueSpec(VALUETYPE_FLAG, _("Show allowed options")))); allowed_options.insert(std::make_pair("version", ValueSpec(VALUETYPE_FLAG, _("Show version information")))); allowed_options.insert(std::make_pair("config", ValueSpec(VALUETYPE_STRING, _("Load configuration from specified file")))); allowed_options.insert(std::make_pair("port", ValueSpec(VALUETYPE_STRING, _("Set network port (UDP)")))); allowed_options.insert(std::make_pair("disable-unittests", ValueSpec(VALUETYPE_FLAG, _("Disable unit tests")))); allowed_options.insert(std::make_pair("enable-unittests", ValueSpec(VALUETYPE_FLAG, _("Enable unit tests")))); allowed_options.insert(std::make_pair("map-dir", ValueSpec(VALUETYPE_STRING, _("Same as --world (deprecated)")))); allowed_options.insert(std::make_pair("world", ValueSpec(VALUETYPE_STRING, _("Set world path (implies local game) ('list' lists all)")))); allowed_options.insert(std::make_pair("worldname", ValueSpec(VALUETYPE_STRING, _("Set world by name (implies local game)")))); allowed_options.insert(std::make_pair("info", ValueSpec(VALUETYPE_FLAG, _("Print more information to console")))); allowed_options.insert(std::make_pair("verbose", ValueSpec(VALUETYPE_FLAG, _("Print even more information to console")))); allowed_options.insert(std::make_pair("trace", ValueSpec(VALUETYPE_FLAG, _("Print enormous amounts of information to log and console")))); allowed_options.insert(std::make_pair("logfile", ValueSpec(VALUETYPE_STRING, _("Set logfile path ('' = no logging)")))); allowed_options.insert(std::make_pair("gameid", ValueSpec(VALUETYPE_STRING, _("Set gameid (\"--gameid list\" prints available ones)")))); allowed_options.insert(std::make_pair("migrate", ValueSpec(VALUETYPE_STRING, _("Migrate from current map backend to another (Only works when using minetestserver or with --server)")))); #ifndef SERVER allowed_options.insert(std::make_pair("videomodes", ValueSpec(VALUETYPE_FLAG, _("Show available video modes")))); allowed_options.insert(std::make_pair("speedtests", ValueSpec(VALUETYPE_FLAG, _("Run speed tests")))); allowed_options.insert(std::make_pair("address", ValueSpec(VALUETYPE_STRING, _("Address to connect to. ('' = local game)")))); allowed_options.insert(std::make_pair("random-input", ValueSpec(VALUETYPE_FLAG, _("Enable random user input, for testing")))); allowed_options.insert(std::make_pair("server", ValueSpec(VALUETYPE_FLAG, _("Run dedicated server")))); allowed_options.insert(std::make_pair("name", ValueSpec(VALUETYPE_STRING, _("Set player name")))); allowed_options.insert(std::make_pair("password", ValueSpec(VALUETYPE_STRING, _("Set password")))); allowed_options.insert(std::make_pair("go", ValueSpec(VALUETYPE_FLAG, _("Disable main menu")))); #endif Settings cmd_args; bool ret = cmd_args.parseCommandLine(argc, argv, allowed_options); if(ret == false || cmd_args.getFlag("help") || cmd_args.exists("nonopt1")) { dstream<<_("Allowed options:")<<std::endl; for(std::map<std::string, ValueSpec>::iterator i = allowed_options.begin(); i != allowed_options.end(); ++i) { std::ostringstream os1(std::ios::binary); os1<<" --"<<i->first; if(i->second.type == VALUETYPE_FLAG) {} else os1<<_(" <value>"); dstream<<padStringRight(os1.str(), 24); if(i->second.help != NULL) dstream<<i->second.help; dstream<<std::endl; } return cmd_args.getFlag("help") ? 0 : 1; } if(cmd_args.getFlag("version")) { #ifdef SERVER dstream<<"minetestserver "<<minetest_version_hash<<std::endl; #else dstream<<"Minetest "<<minetest_version_hash<<std::endl; dstream<<"Using Irrlicht "<<IRRLICHT_SDK_VERSION<<std::endl; #endif dstream<<"Build info: "<<minetest_build_info<<std::endl; return 0; } /* Low-level initialization */ // If trace is enabled, enable logging of certain things if(cmd_args.getFlag("trace")){ dstream<<_("Enabling trace level debug output")<<std::endl; log_trace_level_enabled = true; dout_con_ptr = &verbosestream; // this is somewhat old crap socket_enable_debug_output = true; // socket doesn't use log.h } // In certain cases, output info level on stderr if(cmd_args.getFlag("info") || cmd_args.getFlag("verbose") || cmd_args.getFlag("trace") || cmd_args.getFlag("speedtests")) log_add_output(&main_stderr_log_out, LMT_INFO); // In certain cases, output verbose level on stderr if(cmd_args.getFlag("verbose") || cmd_args.getFlag("trace")) log_add_output(&main_stderr_log_out, LMT_VERBOSE); porting::signal_handler_init(); bool &kill = *porting::signal_handler_killstatus(); porting::initializePaths(); // Create user data directory fs::CreateDir(porting::path_user); infostream<<"path_share = "<<porting::path_share<<std::endl; infostream<<"path_user = "******"gameid") && cmd_args.get("gameid") == "list") { std::set<std::string> gameids = getAvailableGameIds(); for(std::set<std::string>::const_iterator i = gameids.begin(); i != gameids.end(); i++) dstream<<(*i)<<std::endl; return 0; } // List worlds if requested if(cmd_args.exists("world") && cmd_args.get("world") == "list"){ dstream<<_("Available worlds:")<<std::endl; std::vector<WorldSpec> worldspecs = getAvailableWorlds(); print_worldspecs(worldspecs, dstream); return 0; } // Print startup message infostream<<PROJECT_NAME<< " "<<_("with")<<" SER_FMT_VER_HIGHEST_READ="<<(int)SER_FMT_VER_HIGHEST_READ <<", "<<minetest_build_info <<std::endl; /* Basic initialization */ // Initialize default settings set_default_settings(g_settings); // Initialize sockets sockets_init(); atexit(sockets_cleanup); /* Read config file */ // Path of configuration file in use g_settings_path = ""; if(cmd_args.exists("config")) { bool r = g_settings->readConfigFile(cmd_args.get("config").c_str()); if(r == false) { errorstream<<"Could not read configuration from \"" <<cmd_args.get("config")<<"\""<<std::endl; return 1; } g_settings_path = cmd_args.get("config"); } else { std::vector<std::string> filenames; filenames.push_back(porting::path_user + DIR_DELIM + "minetest.conf"); // Legacy configuration file location filenames.push_back(porting::path_user + DIR_DELIM + ".." + DIR_DELIM + "minetest.conf"); #if RUN_IN_PLACE // Try also from a lower level (to aid having the same configuration // for many RUN_IN_PLACE installs) filenames.push_back(porting::path_user + DIR_DELIM + ".." + DIR_DELIM + ".." + DIR_DELIM + "minetest.conf"); #endif for(u32 i=0; i<filenames.size(); i++) { bool r = g_settings->readConfigFile(filenames[i].c_str()); if(r) { g_settings_path = filenames[i]; break; } } // If no path found, use the first one (menu creates the file) if(g_settings_path == "") g_settings_path = filenames[0]; } // Initialize debug streams #define DEBUGFILE "debug.txt" #if RUN_IN_PLACE std::string logfile = DEBUGFILE; #else std::string logfile = porting::path_user+DIR_DELIM+DEBUGFILE; #endif if(cmd_args.exists("logfile")) logfile = cmd_args.get("logfile"); log_remove_output(&main_dstream_no_stderr_log_out); int loglevel = g_settings->getS32("debug_log_level"); if (loglevel == 0) //no logging logfile = ""; else if (loglevel > 0 && loglevel <= LMT_NUM_VALUES) log_add_output_maxlev(&main_dstream_no_stderr_log_out, (LogMessageLevel)(loglevel - 1)); if(logfile != "") debugstreams_init(false, logfile.c_str()); else debugstreams_init(false, NULL); infostream<<"logfile = "<<logfile<<std::endl; // Initialize random seed srand(time(0)); mysrand(time(0)); // Initialize HTTP fetcher httpfetch_init(g_settings->getS32("curl_parallel_limit")); /* Run unit tests */ if((ENABLE_TESTS && cmd_args.getFlag("disable-unittests") == false) || cmd_args.getFlag("enable-unittests") == true) { run_tests(); } #ifdef _MSC_VER init_gettext((porting::path_share + DIR_DELIM + "locale").c_str(),g_settings->get("language"),argc,argv); #else init_gettext((porting::path_share + DIR_DELIM + "locale").c_str(),g_settings->get("language")); #endif /* Game parameters */ // Port u16 port = 30000; if(cmd_args.exists("port")) port = cmd_args.getU16("port"); else if(g_settings->exists("port")) port = g_settings->getU16("port"); if(port == 0) port = 30000; // World directory std::string commanded_world = ""; if(cmd_args.exists("world")) commanded_world = cmd_args.get("world"); else if(cmd_args.exists("map-dir")) commanded_world = cmd_args.get("map-dir"); else if(cmd_args.exists("nonopt0")) // First nameless argument commanded_world = cmd_args.get("nonopt0"); else if(g_settings->exists("map-dir")) commanded_world = g_settings->get("map-dir"); // World name std::string commanded_worldname = ""; if(cmd_args.exists("worldname")) commanded_worldname = cmd_args.get("worldname"); // Strip world.mt from commanded_world { std::string worldmt = "world.mt"; if(commanded_world.size() > worldmt.size() && commanded_world.substr(commanded_world.size()-worldmt.size()) == worldmt){ dstream<<_("Supplied world.mt file - stripping it off.")<<std::endl; commanded_world = commanded_world.substr( 0, commanded_world.size()-worldmt.size()); } } // If a world name was specified, convert it to a path if(commanded_worldname != ""){ // Get information about available worlds std::vector<WorldSpec> worldspecs = getAvailableWorlds(); bool found = false; for(u32 i=0; i<worldspecs.size(); i++){ std::string name = worldspecs[i].name; if(name == commanded_worldname){ if(commanded_world != ""){ dstream<<_("--worldname takes precedence over previously " "selected world.")<<std::endl; } commanded_world = worldspecs[i].path; found = true; break; } } if(!found){ dstream<<_("World")<<" '"<<commanded_worldname<<_("' not " "available. Available worlds:")<<std::endl; print_worldspecs(worldspecs, dstream); return 1; } } // Gamespec SubgameSpec commanded_gamespec; if(cmd_args.exists("gameid")){ std::string gameid = cmd_args.get("gameid"); commanded_gamespec = findSubgame(gameid); if(!commanded_gamespec.isValid()){ errorstream<<"Game \""<<gameid<<"\" not found"<<std::endl; return 1; } } /* Run dedicated server if asked to or no other option */ #ifdef SERVER bool run_dedicated_server = true; #else bool run_dedicated_server = cmd_args.getFlag("server"); #endif g_settings->set("server_dedicated", run_dedicated_server ? "true" : "false"); if(run_dedicated_server) { DSTACK("Dedicated server branch"); // Create time getter if built with Irrlicht #ifndef SERVER g_timegetter = new SimpleTimeGetter(); #endif // World directory std::string world_path; verbosestream<<_("Determining world path")<<std::endl; bool is_legacy_world = false; // If a world was commanded, use it if(commanded_world != ""){ world_path = commanded_world; infostream<<"Using commanded world path ["<<world_path<<"]" <<std::endl; } // No world was specified; try to select it automatically else { // Get information about available worlds std::vector<WorldSpec> worldspecs = getAvailableWorlds(); // If a world name was specified, select it if(commanded_worldname != ""){ world_path = ""; for(u32 i=0; i<worldspecs.size(); i++){ std::string name = worldspecs[i].name; if(name == commanded_worldname){ world_path = worldspecs[i].path; break; } } if(world_path == ""){ dstream<<_("World")<<" '"<<commanded_worldname<<"' "<<_("not " "available. Available worlds:")<<std::endl; print_worldspecs(worldspecs, dstream); return 1; } } // If there is only a single world, use it if(worldspecs.size() == 1){ world_path = worldspecs[0].path; dstream<<_("Automatically selecting world at")<<" [" <<world_path<<"]"<<std::endl; // If there are multiple worlds, list them } else if(worldspecs.size() > 1){ dstream<<_("Multiple worlds are available.")<<std::endl; dstream<<_("Please select one using --worldname <name>" " or --world <path>")<<std::endl; print_worldspecs(worldspecs, dstream); return 1; // If there are no worlds, automatically create a new one } else { // This is the ultimate default world path world_path = porting::path_user + DIR_DELIM + "worlds" + DIR_DELIM + "world"; infostream<<"Creating default world at [" <<world_path<<"]"<<std::endl; } } if(world_path == ""){ errorstream<<"No world path specified or found."<<std::endl; return 1; } verbosestream<<_("Using world path")<<" ["<<world_path<<"]"<<std::endl; // We need a gamespec. SubgameSpec gamespec; verbosestream<<_("Determining gameid/gamespec")<<std::endl; // If world doesn't exist if(!getWorldExists(world_path)) { // Try to take gamespec from command line if(commanded_gamespec.isValid()){ gamespec = commanded_gamespec; infostream<<"Using commanded gameid ["<<gamespec.id<<"]"<<std::endl; } // Otherwise we will be using "minetest" else{ gamespec = findSubgame(g_settings->get("default_game")); infostream<<"Using default gameid ["<<gamespec.id<<"]"<<std::endl; } } // World exists else { std::string world_gameid = getWorldGameId(world_path, is_legacy_world); // If commanded to use a gameid, do so if(commanded_gamespec.isValid()){ gamespec = commanded_gamespec; if(commanded_gamespec.id != world_gameid){ errorstream<<"WARNING: Using commanded gameid [" <<gamespec.id<<"]"<<" instead of world gameid [" <<world_gameid<<"]"<<std::endl; } } else{ // If world contains an embedded game, use it; // Otherwise find world from local system. gamespec = findWorldSubgame(world_path); infostream<<"Using world gameid ["<<gamespec.id<<"]"<<std::endl; } } if(!gamespec.isValid()){ errorstream<<"Subgame ["<<gamespec.id<<"] could not be found." <<std::endl; return 1; } verbosestream<<_("Using gameid")<<" ["<<gamespec.id<<"]"<<std::endl; // Bind address std::string bind_str = g_settings->get("bind_address"); Address bind_addr(0,0,0,0, port); if (g_settings->getBool("ipv6_server")) { bind_addr.setAddress((IPv6AddressBytes*) NULL); } try { bind_addr.Resolve(bind_str.c_str()); } catch (ResolveError &e) { infostream << "Resolving bind address \"" << bind_str << "\" failed: " << e.what() << " -- Listening on all addresses." << std::endl; } if(bind_addr.isIPv6() && !g_settings->getBool("enable_ipv6")) { errorstream << "Unable to listen on " << bind_addr.serializeString() << L" because IPv6 is disabled" << std::endl; return 1; } // Create server Server server(world_path, gamespec, false, bind_addr.isIPv6()); // Database migration if (cmd_args.exists("migrate")) { std::string migrate_to = cmd_args.get("migrate"); Settings world_mt; bool success = world_mt.readConfigFile((world_path + DIR_DELIM + "world.mt").c_str()); if (!success) { errorstream << "Cannot read world.mt" << std::endl; return 1; } if (!world_mt.exists("backend")) { errorstream << "Please specify your current backend in world.mt file:" << std::endl << " backend = {sqlite3|leveldb|redis|dummy}" << std::endl; return 1; } std::string backend = world_mt.get("backend"); Database *new_db; if (backend == migrate_to) { errorstream << "Cannot migrate: new backend is same as the old one" << std::endl; return 1; } if (migrate_to == "sqlite3") new_db = new Database_SQLite3(&(ServerMap&)server.getMap(), world_path); #if USE_LEVELDB else if (migrate_to == "leveldb") new_db = new Database_LevelDB(&(ServerMap&)server.getMap(), world_path); #endif #if USE_REDIS else if (migrate_to == "redis") new_db = new Database_Redis(&(ServerMap&)server.getMap(), world_path); #endif else { errorstream << "Migration to " << migrate_to << " is not supported" << std::endl; return 1; } std::list<v3s16> blocks; ServerMap &old_map = ((ServerMap&)server.getMap()); old_map.listAllLoadableBlocks(blocks); int count = 0; new_db->beginSave(); for (std::list<v3s16>::iterator i = blocks.begin(); i != blocks.end(); ++i) { MapBlock *block = old_map.loadBlock(*i); new_db->saveBlock(block); MapSector *sector = old_map.getSectorNoGenerate(v2s16(i->X, i->Z)); sector->deleteBlock(block); ++count; if (count % 500 == 0) actionstream << "Migrated " << count << " blocks " << (100.0 * count / blocks.size()) << "% completed" << std::endl; } new_db->endSave(); delete new_db; actionstream << "Successfully migrated " << count << " blocks" << std::endl; world_mt.set("backend", migrate_to); if(!world_mt.updateConfigFile((world_path + DIR_DELIM + "world.mt").c_str())) errorstream<<"Failed to update world.mt!"<<std::endl; else actionstream<<"world.mt updated"<<std::endl; return 0; } server.start(bind_addr); // Run server dedicated_server_loop(server, kill); return 0; } #ifndef SERVER // Exclude from dedicated server build /* More parameters */ std::string address = g_settings->get("address"); if(commanded_world != "") address = ""; else if(cmd_args.exists("address")) address = cmd_args.get("address"); std::string playername = g_settings->get("name"); if(cmd_args.exists("name")) playername = cmd_args.get("name"); bool skip_main_menu = cmd_args.getFlag("go"); /* Device initialization */ // Resolution selection bool fullscreen = g_settings->getBool("fullscreen"); u16 screenW = g_settings->getU16("screenW"); u16 screenH = g_settings->getU16("screenH"); // bpp, fsaa, vsync bool vsync = g_settings->getBool("vsync"); u16 bits = g_settings->getU16("fullscreen_bpp"); u16 fsaa = g_settings->getU16("fsaa"); // Determine driver video::E_DRIVER_TYPE driverType; std::string driverstring = g_settings->get("video_driver"); if(driverstring == "null") driverType = video::EDT_NULL; else if(driverstring == "software") driverType = video::EDT_SOFTWARE; else if(driverstring == "burningsvideo") driverType = video::EDT_BURNINGSVIDEO; else if(driverstring == "direct3d8") driverType = video::EDT_DIRECT3D8; else if(driverstring == "direct3d9") driverType = video::EDT_DIRECT3D9; else if(driverstring == "opengl") driverType = video::EDT_OPENGL; #ifdef _IRR_COMPILE_WITH_OGLES1_ else if(driverstring == "ogles1") driverType = video::EDT_OGLES1; #endif #ifdef _IRR_COMPILE_WITH_OGLES2_ else if(driverstring == "ogles2") driverType = video::EDT_OGLES2; #endif else { errorstream<<"WARNING: Invalid video_driver specified; defaulting " "to opengl"<<std::endl; driverType = video::EDT_OPENGL; } /* List video modes if requested */ MyEventReceiver receiver; if(cmd_args.getFlag("videomodes")){ IrrlichtDevice *nulldevice; SIrrlichtCreationParameters params = SIrrlichtCreationParameters(); params.DriverType = video::EDT_NULL; params.WindowSize = core::dimension2d<u32>(640, 480); params.Bits = 24; params.AntiAlias = fsaa; params.Fullscreen = false; params.Stencilbuffer = false; params.Vsync = vsync; params.EventReceiver = &receiver; params.HighPrecisionFPU = g_settings->getBool("high_precision_fpu"); nulldevice = createDeviceEx(params); if(nulldevice == 0) return 1; dstream<<_("Available video modes (WxHxD):")<<std::endl; video::IVideoModeList *videomode_list = nulldevice->getVideoModeList(); if(videomode_list == 0){ nulldevice->drop(); return 1; } s32 videomode_count = videomode_list->getVideoModeCount(); core::dimension2d<u32> videomode_res; s32 videomode_depth; for (s32 i = 0; i < videomode_count; ++i){ videomode_res = videomode_list->getVideoModeResolution(i); videomode_depth = videomode_list->getVideoModeDepth(i); dstream<<videomode_res.Width<<"x"<<videomode_res.Height <<"x"<<videomode_depth<<std::endl; } dstream<<_("Active video mode (WxHxD):")<<std::endl; videomode_res = videomode_list->getDesktopResolution(); videomode_depth = videomode_list->getDesktopDepth(); dstream<<videomode_res.Width<<"x"<<videomode_res.Height <<"x"<<videomode_depth<<std::endl; nulldevice->drop(); return 0; } /* Create device and exit if creation failed */ IrrlichtDevice *device; SIrrlichtCreationParameters params = SIrrlichtCreationParameters(); params.DriverType = driverType; params.WindowSize = core::dimension2d<u32>(screenW, screenH); params.Bits = bits; params.AntiAlias = fsaa; params.Fullscreen = fullscreen; params.Stencilbuffer = false; params.Vsync = vsync; params.EventReceiver = &receiver; params.HighPrecisionFPU = g_settings->getBool("high_precision_fpu"); device = createDeviceEx(params); if (device == 0) return 1; // could not create selected driver. /* Continue initialization */ video::IVideoDriver* driver = device->getVideoDriver(); /* This changes the minimum allowed number of vertices in a VBO. Default is 500. */ //driver->setMinHardwareBufferVertexCount(50); // Create time getter g_timegetter = new IrrlichtTimeGetter(device); // Create game callback for menus g_gamecallback = new MainGameCallback(device); /* Speed tests (done after irrlicht is loaded to get timer) */ if(cmd_args.getFlag("speedtests")) { dstream<<"Running speed tests"<<std::endl; SpeedTests(); device->drop(); return 0; } device->setResizable(true); bool random_input = g_settings->getBool("random_input") || cmd_args.getFlag("random-input"); InputHandler *input = NULL; if(random_input) { input = new RandomInputHandler(); } else { input = new RealInputHandler(device, &receiver); } scene::ISceneManager* smgr = device->getSceneManager(); guienv = device->getGUIEnvironment(); gui::IGUISkin* skin = guienv->getSkin(); std::string font_path = g_settings->get("font_path"); gui::IGUIFont *font; #if USE_FREETYPE bool use_freetype = g_settings->getBool("freetype"); if (use_freetype) { std::string fallback; if (is_yes(gettext("needs_fallback_font"))) fallback = "fallback_"; u16 font_size = g_settings->getU16(fallback + "font_size"); font_path = g_settings->get(fallback + "font_path"); u32 font_shadow = g_settings->getU16(fallback + "font_shadow"); u32 font_shadow_alpha = g_settings->getU16(fallback + "font_shadow_alpha"); font = gui::CGUITTFont::createTTFont(guienv, font_path.c_str(), font_size, true, true, font_shadow, font_shadow_alpha); } else { font = guienv->getFont(font_path.c_str()); } #else font = guienv->getFont(font_path.c_str()); #endif if(font) skin->setFont(font); else errorstream<<"WARNING: Font file was not found." " Using default font."<<std::endl; // If font was not found, this will get us one font = skin->getFont(); assert(font); u32 text_height = font->getDimension(L"Hello, world!").Height; infostream<<"text_height="<<text_height<<std::endl; //skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,0,0,0)); skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,255,255,255)); //skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(0,0,0,0)); //skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(0,0,0,0)); skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(255,0,0,0)); skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(255,0,0,0)); skin->setColor(gui::EGDC_HIGH_LIGHT, video::SColor(255,70,100,50)); skin->setColor(gui::EGDC_HIGH_LIGHT_TEXT, video::SColor(255,255,255,255)); #if (IRRLICHT_VERSION_MAJOR >= 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR >= 2 // Irrlicht 1.8 input colours skin->setColor(gui::EGDC_EDITABLE, video::SColor(255,128,128,128)); skin->setColor(gui::EGDC_FOCUSED_EDITABLE, video::SColor(255,96,134,49)); #endif // Create the menu clouds if (!g_menucloudsmgr) g_menucloudsmgr = smgr->createNewSceneManager(); if (!g_menuclouds) g_menuclouds = new Clouds(g_menucloudsmgr->getRootSceneNode(), g_menucloudsmgr, -1, rand(), 100); g_menuclouds->update(v2f(0, 0), video::SColor(255,200,200,255)); scene::ICameraSceneNode* camera; camera = g_menucloudsmgr->addCameraSceneNode(0, v3f(0,0,0), v3f(0, 60, 100)); camera->setFarValue(10000); /* GUI stuff */ ChatBackend chat_backend; /* If an error occurs, this is set to something and the menu-game loop is restarted. It is then displayed before the menu. */ std::wstring error_message = L""; // The password entered during the menu screen, std::string password; bool first_loop = true; /* Menu-game loop */ while(device->run() && kill == false) { // Set the window caption wchar_t* text = wgettext("Main Menu"); device->setWindowCaption((std::wstring(L"Minetest [")+text+L"]").c_str()); delete[] text; // This is used for catching disconnects try { /* Clear everything from the GUIEnvironment */ guienv->clear(); /* We need some kind of a root node to be able to add custom gui elements directly on the screen. Otherwise they won't be automatically drawn. */ guiroot = guienv->addStaticText(L"", core::rect<s32>(0, 0, 10000, 10000)); SubgameSpec gamespec; WorldSpec worldspec; bool simple_singleplayer_mode = false; // These are set up based on the menu and other things std::string current_playername = "inv£lid"; std::string current_password = ""; std::string current_address = "does-not-exist"; int current_port = 0; /* Out-of-game menu loop. Loop quits when menu returns proper parameters. */ while(kill == false) { // If skip_main_menu, only go through here once if(skip_main_menu && !first_loop){ kill = true; break; } first_loop = false; // Cursor can be non-visible when coming from the game device->getCursorControl()->setVisible(true); // Some stuff are left to scene manager when coming from the game // (map at least?) smgr->clear(); // Initialize menu data MainMenuData menudata; menudata.address = address; menudata.name = playername; menudata.port = itos(port); menudata.errormessage = wide_to_narrow(error_message); error_message = L""; if(cmd_args.exists("password")) menudata.password = cmd_args.get("password"); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, g_settings->getBool("mip_map")); menudata.enable_public = g_settings->getBool("server_announce"); std::vector<WorldSpec> worldspecs = getAvailableWorlds(); // If a world was commanded, append and select it if(commanded_world != ""){ std::string gameid = getWorldGameId(commanded_world, true); std::string name = _("[--world parameter]"); if(gameid == ""){ gameid = g_settings->get("default_game"); name += " [new]"; } //TODO find within worldspecs and set config } if(skip_main_menu == false) { video::IVideoDriver* driver = device->getVideoDriver(); infostream<<"Waiting for other menus"<<std::endl; while(device->run() && kill == false) { if(noMenuActive()) break; driver->beginScene(true, true, video::SColor(255,128,128,128)); guienv->drawAll(); driver->endScene(); // On some computers framerate doesn't seem to be // automatically limited sleep_ms(25); } infostream<<"Waited for other menus"<<std::endl; GUIEngine* temp = new GUIEngine(device, guiroot, &g_menumgr,smgr,&menudata,kill); delete temp; //once finished you'll never end up here smgr->clear(); } if(menudata.errormessage != ""){ error_message = narrow_to_wide(menudata.errormessage); continue; } //update worldspecs (necessary as new world may have been created) worldspecs = getAvailableWorlds(); if (menudata.name == "") menudata.name = std::string("Guest") + itos(myrand_range(1000,9999)); else playername = menudata.name; password = translatePassword(playername, narrow_to_wide(menudata.password)); //infostream<<"Main: password hash: '"<<password<<"'"<<std::endl; address = menudata.address; int newport = stoi(menudata.port); if(newport != 0) port = newport; simple_singleplayer_mode = menudata.simple_singleplayer_mode; // Save settings g_settings->set("name", playername); if((menudata.selected_world >= 0) && (menudata.selected_world < (int)worldspecs.size())) g_settings->set("selected_world_path", worldspecs[menudata.selected_world].path); // Break out of menu-game loop to shut down cleanly if(device->run() == false || kill == true) break; current_playername = playername; current_password = password; current_address = address; current_port = port; // If using simple singleplayer mode, override if(simple_singleplayer_mode){ current_playername = "singleplayer"; current_password = ""; current_address = ""; current_port = myrand_range(49152, 65535); } else if (address != "") { ServerListSpec server; server["name"] = menudata.servername; server["address"] = menudata.address; server["port"] = menudata.port; server["description"] = menudata.serverdescription; ServerList::insert(server); } // Set world path to selected one if ((menudata.selected_world >= 0) && (menudata.selected_world < (int)worldspecs.size())) { worldspec = worldspecs[menudata.selected_world]; infostream<<"Selected world: "<<worldspec.name <<" ["<<worldspec.path<<"]"<<std::endl; } // If local game if(current_address == "") { if(menudata.selected_world == -1){ error_message = wgettext("No world selected and no address " "provided. Nothing to do."); errorstream<<wide_to_narrow(error_message)<<std::endl; continue; } // Load gamespec for required game gamespec = findWorldSubgame(worldspec.path); if(!gamespec.isValid() && !commanded_gamespec.isValid()){ error_message = wgettext("Could not find or load game \"") + narrow_to_wide(worldspec.gameid) + L"\""; errorstream<<wide_to_narrow(error_message)<<std::endl; continue; } if(commanded_gamespec.isValid() && commanded_gamespec.id != worldspec.gameid){ errorstream<<"WARNING: Overriding gamespec from \"" <<worldspec.gameid<<"\" to \"" <<commanded_gamespec.id<<"\""<<std::endl; gamespec = commanded_gamespec; } if(!gamespec.isValid()){ error_message = wgettext("Invalid gamespec."); error_message += L" (world_gameid=" +narrow_to_wide(worldspec.gameid)+L")"; errorstream<<wide_to_narrow(error_message)<<std::endl; continue; } } // Continue to game break; } // Break out of menu-game loop to shut down cleanly if(device->run() == false || kill == true) { if(g_settings_path != "") { g_settings->updateConfigFile( g_settings_path.c_str()); } break; } /* Run game */ the_game( kill, random_input, input, device, font, worldspec.path, current_playername, current_password, current_address, current_port, error_message, chat_backend, gamespec, simple_singleplayer_mode ); smgr->clear(); } //try catch(con::PeerNotFoundException &e) { error_message = wgettext("Connection error (timed out?)"); errorstream<<wide_to_narrow(error_message)<<std::endl; } #ifdef NDEBUG catch(std::exception &e) { std::string narrow_message = "Some exception: \""; narrow_message += e.what(); narrow_message += "\""; errorstream<<narrow_message<<std::endl; error_message = narrow_to_wide(narrow_message); } #endif // If no main menu, show error and exit if(skip_main_menu) { if(error_message != L""){ verbosestream<<"error_message = " <<wide_to_narrow(error_message)<<std::endl; retval = 1; } break; } } // Menu-game loop g_menuclouds->drop(); g_menucloudsmgr->drop(); delete input; /* In the end, delete the Irrlicht device. */ device->drop(); #if USE_FREETYPE if (use_freetype) font->drop(); #endif #endif // !SERVER // Update configuration file if(g_settings_path != "") g_settings->updateConfigFile(g_settings_path.c_str()); // Print modified quicktune values { bool header_printed = false; std::vector<std::string> names = getQuicktuneNames(); for(u32 i=0; i<names.size(); i++){ QuicktuneValue val = getQuicktuneValue(names[i]); if(!val.modified) continue; if(!header_printed){ dstream<<"Modified quicktune values:"<<std::endl; header_printed = true; } dstream<<names[i]<<" = "<<val.getString()<<std::endl; } } // Stop httpfetch thread (if started) httpfetch_cleanup(); END_DEBUG_EXCEPTION_HANDLER(errorstream) debugstreams_deinit(); return retval; }
int main() { // driver type video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D9; // create device IrrlichtDevice *device = createDevice(driverType, core::dimension2d<u32>(640, 480), 16, false ); if ( device == 0 ) { return 1; } // create engine and camera device->setWindowCaption(L"Custom Scene Node - Irrlicht Engine Demo "); video::IVideoDriver *driver = device->getVideoDriver(); scene::ISceneManager *smgr = device->getSceneManager(); smgr->addCameraSceneNode(0, core::vector3df(0,-40,0), core::vector3df(0,0,0)); CSampleSceneNode *myNode = new CSampleSceneNode(smgr->getRootSceneNode(), smgr, 666); scene::ISceneNodeAnimator *anim = smgr->createRotationAnimator(core::vector3df(0.8f, 0, 0.8f)); if (anim) { myNode->addAnimator(anim); anim->drop(); anim = 0; // ensure i can not refer to it again. } myNode->drop(); myNode = 0; // ensure i can not refer to it again. // draw everything u32 frames = 0; while (device->run()) { driver->beginScene(true, true, video::SColor(0, 100, 100, 100)); smgr->drawAll(); driver->endScene(); if (++frames==100) { core::stringw str = L"Irrlicht Engine ["; str += driver->getName(); str += L"] FPS: "; str += (s32)driver->getFPS(); device->setWindowCaption(str.c_str()); frames = 0; } } driver->drop(); return 0; }
int main() { srand(time(NULL)); int numPlayers = 4; //Setup irrlicht MyEventReceiver Receiver; IrrlichtDevice *device = createDevice(EDT_OPENGL,dimension2d<u32>(SCREENX,SCREENY),32,FULLSCREEN,false,false,&Receiver); IVideoDriver* driver = device->getVideoDriver(); ISceneManager* smgr = device->getSceneManager(); IGUIEnvironment* guienv = device->getGUIEnvironment(); //Load key config Receiver.KeyConfig.loadFromFile("KeyConfig.txt"); //Generate maze MazeGenerator MG; /* MG.NewSize(495,497,495,497); MG.Generate("DrunkenWalk2",500,numPlayers);//500,numPlayers); MG.Minimise(); MG.MinimalSolids(false); MG.ConvertLoneToCover();*/ MG.MapFromFile("Maps/01g.txt", "Maps/01m.txt", "Maps/01e.txt"); vector<int> PlayerStartPos; PlayerStartPos.push_back(10); PlayerStartPos.push_back(11); PlayerStartPos.push_back(12); PlayerStartPos.push_back(13); MG.ParseForPlayerStartPositions(PlayerStartPos); //Setup textures ITexture *FloorTexture = driver->getTexture("Textures/Floor.png"); ITexture *WallTexture = driver->getTexture("Textures/Wall.png"); ITexture *CoverTexture = driver->getTexture("Textures/Cover.png"); //Import maze MazeRenderer MR; MR.CreateFromMazeGenerator( MG, smgr ); MR.SetTextures( FloorTexture, WallTexture, CoverTexture ); //Setup camera GameCamera gameCam(70); gameCam.camera = smgr->addCameraSceneNode(); gameCam.camera->setPosition( vector3df( (MR.XSize/2)*MR.TileSize, 40, (MR.YSize/2)*MR.TileSize ) ); gameCam.camera->setRotation( vector3df(0,90,90)); //Create players (4) for testing //Have to use an array as you can't copy boost::threads which pushing into vectors does EntityManager PlayerManager(numPlayers); //Textures ITexture* PlayerTexture[4]; PlayerTexture[0] = driver->getTexture("Textures/Player1.png"); PlayerTexture[1] = driver->getTexture("Textures/Player2.png"); PlayerTexture[2] = driver->getTexture("Textures/Player3.png"); PlayerTexture[3] = driver->getTexture("Textures/Player4.png"); //Names vector<std::string> PlayerName; PlayerName.push_back("Motoko"); PlayerName.push_back("Saito"); PlayerName.push_back("Batou"); PlayerName.push_back("Togusa"); //use this method to get starting cells for an enemy group vector<v2d> vv = GetFreeCells(MG.Convert(),MG.StartX,MG.StartY,4); //HUD test hud HUD(guienv,dimension2d<s32>(SCREENX,SCREENY),"Font\\myfont.xml"); for (int i = 0; i < numPlayers; i++ ) { PlayerManager.GetEntity(i)->Construct(smgr,MG.Convert(), PlayerTexture[i]); PlayerManager.GetEntity(i)->Stats.Name = PlayerName[i]; PlayerManager.GetEntity(i)->Stats.MaxHealth = 100; PlayerManager.GetEntity(i)->Stats.RestoreAll(); PlayerManager.GetEntity(i)->X = MG.XStarts[i]; PlayerManager.GetEntity(i)->Y = MG.YStarts[i]; PlayerManager.GetEntity(i)->Stats.MovementSteps = 5+i; PlayerManager.GetEntity(i)->ReachableTile = driver->getTexture("Textures/TurnReachable.png"); PlayerManager.GetEntity(i)->UnreachableTile = driver->getTexture("Textures/TurnUnreachable.png"); PlayerManager.GetEntity(i)->Stats.RealFiringDistance = 100; PlayerManager.GetEntity(i)->CellShootable = driver->getTexture("Textures/CellShootable.png"); PlayerManager.GetEntity(i)->CellShootableCover = driver->getTexture("Textures/CellShootableCover.png"); PlayerManager.GetEntity(i)->Position(); path filename = "Avatars/"; filename.append(PlayerName[i].c_str()); filename.append(".png"); PlayerManager.GetEntity(i)->Avatar = driver->getTexture( filename ); //test stats PlayerManager.GetEntity(i)->Stats.Accuracy = 100; PlayerManager.GetEntity(i)->Stats.Attack = 100; PlayerManager.GetEntity(i)->Stats.AttackVariance = 0; PlayerManager.GetEntity(i)->Stats.Defense = 0; PlayerManager.GetEntity(i)->Stats.DefenseVariance = 0; } // Create the 3D cursor ISceneNode *Cursor = smgr->addSphereSceneNode(4); //Setup AI int numEnemies = 1; EntityManager EnemyManager(numEnemies); //Textures (none for now) //Need to keep track of all entity positions, so they don't get placed ontop of each other vector<Entity*> EntityList( PlayerManager.GetEntityList() ); for (int i = 0; i < numEnemies; i++) { EnemyManager.GetEntity(i)->Construct(smgr,MG.Convert(), driver->getTexture("Textures/Enemy.png")); EnemyManager.GetEntity(i)->Stats.Name = PlayerName[i]; EnemyManager.GetEntity(i)->Stats.MaxHealth = 100; EnemyManager.GetEntity(i)->Stats.RestoreAll(); EnemyManager.GetEntity(i)->Stats.MovementSteps = 5+i; EnemyManager.GetEntity(i)->Stats.RealFiringDistance = 100; EnemyManager.GetEntity(i)->Stats.Attack = 50; EnemyManager.GetEntity(i)->Stats.Accuracy = 100; //Stats //steup random position EnemyManager.GetEntity(i)->AI_SetRandomDestination(EntityList); EnemyManager.GetEntity(i)->X = EnemyManager.GetEntity(i)->AI_DestinationX; EnemyManager.GetEntity(i)->Y = EnemyManager.GetEntity(i)->AI_DestinationY; //new path will be created EnemyManager.GetEntity(i)->Position(); EnemyManager.GetEntity(i)->AI_State = AI::Patrol; EnemyManager.GetEntity(i)->isAI = true; EntityList.push_back(EnemyManager.GetEntity(i)); } bool rkf = false; //Game loop while (device->run()) { //Create a list of all entities EntityList.clear(); vector<Entity*> EnemyList( EnemyManager.GetEntityList() ); EntityList.insert( EntityList.end(), EnemyList.begin(), EnemyList.end() ); /* * * * * * * * * * * * * * */ /* Player switching module */ /* * * * * * * * * * * * * * */ for (int i = 0; i < PlayerManager.Size; i++) PlayerManager.GetEntity(i)->CheckIfDead(); PlayerManager.ManageCharacterSwitching(Receiver); /* * * * * * * * * * * */ /* Pathfinding module */ /* * * * * * * * * * * */ PlayerManager.GetCurrentEntity()->UpdatePathDisplayTimer(); if (Receiver.MouseState.LeftButtonDown && PlayerManager.GetCurrentEntity()->NewPathDisplayTimer < 1) PlayerManager.GetCurrentEntity()->CreatePathToDestination(EntityList,smgr,Receiver,Cursor->getPosition(),dimension2d<s32>(MR.XSize,MR.YSize),MG.Convert()); /* * * * * * * * * * * * * */ /* Update position module */ /* * * * * * * * * * * * * */ PlayerManager.GetCurrentEntity()->Position(); /* * * * * * * * * * * */ /* Follow path module */ /* * * * * * * * * * * */ if (Receiver.IsKeyDown(Receiver.KeyConfig.FOLLOW_PATH)) PlayerManager.GetCurrentEntity()->FollowPath(EntityList); /* * * * * * * * * */ /* End turn module */ /* * * * * * * * * */ if (Receiver.IsKeyDown(Receiver.KeyConfig.END_TURN) && !rkf) { rkf = true; PlayerManager.EndTurn(); EnemyManager.AI_StartTurn(EntityList, PlayerManager, smgr, Receiver, irr::core::dimension2d<s32>(MR.XSize,MR.YSize), MG.Convert(), MR.MetaTriangleSelector, MR.MetaCoverTriangleSelector); PlayerManager.StartTurn(); } else if (!Receiver.IsKeyDown(Receiver.KeyConfig.END_TURN)) rkf = false; /* * * * * * * * */ /* Cursor module */ /* * * * * * * * */ Cursor->setPosition( vftovi(MouseTo3D( Receiver, MR.CollisionManager, MR.TriSelector)) ); /* * * * * * * * */ /* Camera module */ /* * * * * * * * */ gameCam.Update(Receiver,PlayerManager.GetCurrentEntity()->Node); /* * * * * * * * * * * * */ /* Stats monitor module */ /* * * * * * * * * * * * */ for (int i=0;i<PlayerManager.Size;i++) PlayerManager.GetEntity(i)->Stats.MonitorAll(); /* * * * * * * * * * */ /* Draw scene module */ /* * * * * * * * * * */ driver->beginScene(true,true,SColor(255,100,101,140)); smgr->drawAll(); guienv->drawAll(); HUD.Draw(guienv,PlayerManager.GetCurrentEntity()->Stats,PlayerManager.GetCurrentEntity()->Avatar); //HUD.DrawAIDebug(guienv,*EnemyManager.GetEntity(0),PlayerManager); driver->endScene(); /* * * * * * * */ /* Menu module */ /* * * * * * * */ if (Receiver.IsKeyDown(Receiver.KeyConfig.MENU)) return 0; /* * * * * * * * * * * * */ /* Firing display module */ /* * * * * * * * * * * * */ if (!Receiver.IsKeyDown(KEY_KEY_S)) PlayerManager.GetCurrentEntity()->ShootDisplayKeyFlag = false; else { PlayerManager.GetCurrentEntity()->ShootDisplayKeyFlag = true; PlayerManager.GetCurrentEntity()->DisplayAllCellsThatCanBeShotUsingThreads(smgr,MR.CollisionManager,MR.MetaTriangleSelector,MR.MetaCoverTriangleSelector); } /* * * * * * * * * */ /* Firing module * */ /* * * * * * * * * */ if (Receiver.MouseState.RightButtonDown && !PlayerManager.GetCurrentEntity()->RightMouseFlag) { PlayerManager.GetCurrentEntity()->RightMouseFlag = true; //second playerManager needs to replaced with enemyManager when in place, the function will also need to be edited FireAtTarget(Receiver, PlayerManager, EnemyManager, MR, smgr, Cursor); } else if (!Receiver.MouseState.RightButtonDown) PlayerManager.GetCurrentEntity()->RightMouseFlag = false; } return 0; }
int main() { // create device with full flexibility over creation parameters // you can add more parameters if desired, check irr::SIrrlichtCreationParameters irr::SIrrlichtCreationParameters params; params.Bits = 24; //may have to set to 32bit for some platforms params.ZBufferBits = 24; //we'd like 32bit here params.DriverType = video::EDT_OPENGL; //! Only Well functioning driver, software renderer left for sake of 2D image drawing params.WindowSize = core::dimension2d<uint32_t>(1280, 720); params.Fullscreen = false; params.Vsync = true; //! If supported by target platform params.Doublebuffer = true; params.Stencilbuffer = false; //! This will not even be a choice soon IrrlichtDevice* device = createDeviceEx(params); if (device == 0) return 1; // could not create selected driver. video::IVideoDriver* driver = device->getVideoDriver(); uint32_t dim[3] = {params.WindowSize.Width,params.WindowSize.Height,1}; video::ITexture* colorAttach = driver->addTexture(video::ITexture::ETT_2D,dim,1,"no_name_color",irr::video::ECF_R8G8B8A8); video::ITexture* depthAttach = driver->addTexture(video::ITexture::ETT_2D,dim,1,"no_name_depth",irr::video::ECF_DEPTH32F); video::IFrameBuffer* fbo = driver->addFrameBuffer(); fbo->attach(video::EFAP_COLOR_ATTACHMENT0,colorAttach); fbo->attach(video::EFAP_DEPTH_ATTACHMENT,depthAttach); driver->setRenderTarget(fbo); uint64_t lastFPSTime = 0; while(device->run()) { // this should clear backbuffer to red driver->beginScene(true, false, video::SColor(255,255,0,0) ); //these should clear bound FBO driver->clearZBuffer(); float color[4] = {1.f,1.f,1.f,1.f}; driver->clearColorBuffer(video::EFAP_COLOR_ATTACHMENT0,color); for (auto i=0; i<700; i++) { //green { float color[4] = {0.f,1.f,0.f,0.f}; driver->clearScreen(irr::video::ESB_BACK_LEFT,color); } //blue { float color[4] = {0.f,0.f,1.f,1.f}; driver->clearScreen(irr::video::ESB_BACK_LEFT,color); } //black { float color[4] = {0.f,0.f,0.f,1.f}; driver->clearScreen(irr::video::ESB_BACK_LEFT,color); } } driver->blitRenderTargets(fbo,0,false,false); driver->endScene(); // display frames per second in window title uint64_t time = device->getTimer()->getRealTime(); if (time-lastFPSTime > 1000) { std::wostringstream str(L"Hello World - Irrlicht Engine ["); str.seekp(0,std::ios_base::end); str << driver->getName() << "] FPS:" << driver->getFPS(); device->setWindowCaption(str.str()); lastFPSTime = time; } } device->drop(); return 0; }
/* This is the main method. We can now use main() on every platform. */ int main() { /* The most important function of the engine is the createDevice() function. The IrrlichtDevice is created by it, which is the root object for doing anything with the engine. createDevice() has 7 parameters: - deviceType: Type of the device. This can currently be the Null-device, one of the two software renderers, D3D9, or OpenGL. In this example we use EDT_SOFTWARE, but to try out, you might want to change it to EDT_BURNINGSVIDEO, EDT_NULL, EDT_DIRECT3D9, or EDT_OPENGL. - windowSize: Size of the Window or screen in FullScreenMode to be created. In this example we use 640x480. - bits: Amount of color bits per pixel. This should be 16 or 32. The parameter is often ignored when running in windowed mode. - fullscreen: Specifies if we want the device to run in fullscreen mode or not. - stencilbuffer: Specifies if we want to use the stencil buffer (for drawing shadows). - vsync: Specifies if we want to have vsync enabled, this is only useful in fullscreen mode. - eventReceiver: An object to receive events. We do not want to use this parameter here, and set it to 0. Always check the return value to cope with unsupported drivers, dimensions, etc. */ IrrlichtDevice *device = createDevice( video::EDT_OGLES1, dimension2d<u32>(640, 480), 16, false, false, false, 0); if (!device) return 1; /* Set the caption of the window to some nice text. Note that there is an 'L' in front of the string. The Irrlicht Engine uses wide character strings when displaying text. */ device->setWindowCaption(L"Hello World! - Irrlicht Engine Demo"); /* Get a pointer to the VideoDriver, the SceneManager and the graphical user interface environment, so that we do not always have to write device->getVideoDriver(), device->getSceneManager(), or device->getGUIEnvironment(). */ IVideoDriver* driver = device->getVideoDriver(); ISceneManager* smgr = device->getSceneManager(); IGUIEnvironment* guienv = device->getGUIEnvironment(); /* We add a hello world label to the window, using the GUI environment. The text is placed at the position (10,10) as top left corner and (260,22) as lower right corner. */ guienv->addStaticText(L"Hello World! This is the Irrlicht Software renderer!", rect<s32>(10,10,260,22), true); /* Get a media path dedicated for your platform. */ const io::path mediaPath = getExampleMediaPath(); /* To show something interesting, we load a Quake 2 model and display it. We only have to get the Mesh from the Scene Manager with getMesh() and add a SceneNode to display the mesh with addAnimatedMeshSceneNode(). We check the return value of getMesh() to become aware of loading problems and other errors. Instead of writing the filename sydney.md2, it would also be possible to load a Maya object file (.obj), a complete Quake3 map (.bsp) or any other supported file format. By the way, that cool Quake 2 model called sydney was modelled by Brian Collins. */ IAnimatedMesh* mesh = smgr->getMesh(mediaPath + "sydney.md2"); if (!mesh) { device->drop(); return 1; } IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh ); /* To let the mesh look a little bit nicer, we change its material. We disable lighting because we do not have a dynamic light in here, and the mesh would be totally black otherwise. Then we set the frame loop, such that the predefined STAND animation is used. And last, we apply a texture to the mesh. Without it the mesh would be drawn using only a color. */ if (node) { node->setMaterialFlag(EMF_LIGHTING, false); node->setMD2Animation(scene::EMAT_STAND); node->setMaterialTexture( 0, driver->getTexture(mediaPath + "sydney.bmp") ); } /* To look at the mesh, we place a camera into 3d space at the position (0, 30, -40). The camera looks from there to (0,5,0), which is approximately the place where our md2 model is. */ smgr->addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0)); /* Ok, now we have set up the scene, lets draw everything: We run the device in a while() loop, until the device does not want to run any more. This would be when the user closes the window or presses ALT+F4 (or whatever keycode closes a window). */ while(device->run()) { /* Anything can be drawn between a beginScene() and an endScene() call. The beginScene() call clears the screen with a color and the depth buffer, if desired. Then we let the Scene Manager and the GUI Environment draw their content. With the endScene() call everything is presented on the screen. */ driver->beginScene(ECBF_COLOR | ECBF_DEPTH, SColor(255,100,101,140)); smgr->drawAll(); guienv->drawAll(); driver->endScene(); } /* After we are done with the render loop, we have to delete the Irrlicht Device created before with createDevice(). In the Irrlicht Engine, you have to delete all objects you created with a method or function which starts with 'create'. The object is simply deleted by calling ->drop(). See the documentation at irr::IReferenceCounted::drop() for more information. */ device->drop(); return 0; }
/* Ok, now for the more interesting part. First, create the Irrlicht device. As in some examples before, we ask the user which driver he wants to use for this example: */ int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // create device and exit if creation failed IrrlichtDevice * device = createDevice(driverType, core::dimension2d<u32>(640, 480)); if (device == 0) return 1; // could not create selected driver. /* The creation was successful, now we set the event receiver and store pointers to the driver and to the gui environment. */ device->setWindowCaption(L"Irrlicht Engine - User Interface Demo"); device->setResizable(true); video::IVideoDriver* driver = device->getVideoDriver(); IGUIEnvironment* env = device->getGUIEnvironment(); /* To make the font a little bit nicer, we load an external font and set it as the new default font in the skin. To keep the standard font for tool tip text, we set it to the built-in font. */ IGUISkin* skin = env->getSkin(); IGUIFont* font = env->getFont("../../media/fonthaettenschweiler.bmp"); if (font) skin->setFont(font); skin->setFont(env->getBuiltInFont(), EGDF_TOOLTIP); /* We add three buttons. The first one closes the engine. The second creates a window and the third opens a file open dialog. The third parameter is the id of the button, with which we can easily identify the button in the event receiver. */ env->addButton(rect<s32>(10,240,110,240 + 32), 0, GUI_ID_QUIT_BUTTON, L"Quit", L"Exits Program"); env->addButton(rect<s32>(10,280,110,280 + 32), 0, GUI_ID_NEW_WINDOW_BUTTON, L"New Window", L"Launches a new Window"); env->addButton(rect<s32>(10,320,110,320 + 32), 0, GUI_ID_FILE_OPEN_BUTTON, L"File Open", L"Opens a file"); /* Now, we add a static text and a scrollbar, which modifies the transparency of all gui elements. We set the maximum value of the scrollbar to 255, because that's the maximal value for a color value. Then we create an other static text and a list box. */ env->addStaticText(L"Transparent Control:", rect<s32>(150,20,350,40), true); IGUIScrollBar* scrollbar = env->addScrollBar(true, rect<s32>(150, 45, 350, 60), 0, GUI_ID_TRANSPARENCY_SCROLL_BAR); scrollbar->setMax(255); scrollbar->setPos(255); setSkinTransparency( scrollbar->getPos(), env->getSkin()); // set scrollbar position to alpha value of an arbitrary element scrollbar->setPos(env->getSkin()->getColor(EGDC_WINDOW).getAlpha()); env->addStaticText(L"Logging ListBox:", rect<s32>(10,110,350,130), true); IGUIListBox * listbox = env->addListBox(rect<s32>(10, 140, 350, 210)); env->addEditBox(L"Editable Text", rect<s32>(350, 80, 550, 100)); // Store the appropriate data in a context structure. SAppContext context; context.device = device; context.counter = 0; context.listbox = listbox; // Then create the event receiver, giving it that context structure. MyEventReceiver receiver(context); // And tell the device to use our custom event receiver. device->setEventReceiver(&receiver); /* And at last, we create a nice Irrlicht Engine logo in the top left corner. */ env->addImage(driver->getTexture("../../media/irrlichtlogo2.png"), position2d<int>(10,10)); /* That's all, we only have to draw everything. */ while(device->run() && driver) if (device->isWindowActive()) { driver->beginScene(true, true, SColor(0,200,200,200)); env->drawAll(); driver->endScene(); } device->drop(); return 0; }
void ModuleControl::OnEvent( const SEvent& event ) { // 鼠标消息处理 if (event.EventType == EET_MOUSE_INPUT_EVENT) { // 滚轮处理 if (event.MouseInput.Wheel == -1) { vector3df vForward; GetForwardVector(vForward); ModuleposRelateToCamaraVector = ModuleposRelateToCamaraVector*2; setModuleposRelateToCamara(ModuleposRelateToCamaraVector); } if (event.MouseInput.Wheel == 1) { vector3df vForward; GetForwardVector(vForward); ModuleposRelateToCamaraVector = ModuleposRelateToCamaraVector/2; setModuleposRelateToCamara(ModuleposRelateToCamaraVector); } IrrlichtDevice* device = MyIrrlichtEngine::GetEngine()->GetDevice(); CursorPos = device->getCursorControl()->getRelativePosition(); if (CursorPos.equals(CenterCursor)) { return; } if (event.MouseInput.isLeftPressed()) { vector3df v = pModule->getPosition(); matrix4 vm = pCamara->getProjectionMatrix(); //pCamara->get //f32 data[4]; //data[0] = v.X; //data[1] = v.Y; //data[2] = v.Z; //data[3] = 1; //vm.multiplyWith1x4Matrix(data); //std::cout << "a" <<std::endl; } // 鼠标移动处理 f32 xdelta = (CursorPos.Y - CenterCursor.Y)*30; f32 ydelta = (CursorPos.X - CenterCursor.X)*30; if (m_vCamaraRotation.X >= 85.0 && xdelta > 0) { xdelta = 0; } if (m_vCamaraRotation.X <= -85.0 && xdelta < 0) { xdelta = 0; } m_vCamaraRotation += vector3df(xdelta, 0.0, 0.0); m_vCamaraRotation += vector3df(0.0, ydelta, 0.0); SetCamaraRotation(m_vCamaraRotation); device->getCursorControl()->setPosition(CenterCursor); } // 按键消息处理 if (event.EventType == EET_KEY_INPUT_EVENT) { if (event.KeyInput.Key == KEY_KEY_W ) { } if (event.KeyInput.Key == KEY_KEY_S ) { } if (event.KeyInput.Key == KEY_KEY_A ) { m_vModuleRotation += vector3df(0.f, 0.f, 1.f); pModule->setRotation(m_vModuleRotation); } if (event.KeyInput.Key == KEY_KEY_D ) { m_vModuleRotation += vector3df(0.f, 0.f, -1.f); pModule->setRotation(m_vModuleRotation); } if (event.KeyInput.Key == KEY_UP) { } if (event.KeyInput.Key == KEY_DOWN) { } if (event.KeyInput.Key == KEY_LEFT) { } if (event.KeyInput.Key == KEY_RIGHT) { } } }
/* The start of the main function starts like in most other example. We ask the user for the desired renderer and start it up. This time with the advanced parameter handling. */ int example_terrain() { // create device IrrlichtDevice *device = startup(); if (device == 0) return 1; // could not create selected driver. /* First, we add standard stuff to the scene: A nice irrlicht engine logo, a small help text, a user controlled camera, and we disable the mouse cursor. */ video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* env = device->getGUIEnvironment(); //set other font //env->getSkin()->setFont(env->getFont("../../media/fontlucida.png")); // add some help text env->addStaticText( L"Press 'W' to change wireframe mode\nPress 'D' to toggle detail map\nPress 'S' to toggle skybox/skydome", core::rect<s32>(5,250,235,320), true, true, 0, -1, true); // add camera scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(0,100.0f,1.2f); camera->setPosition(core::vector3df(2700*2,255*2,2600*2)); camera->setTarget(core::vector3df(2397*2,343*2,2700*2)); camera->setFarValue(42000.0f); // disable mouse cursor device->getCursorControl()->setVisible(false); /* Here comes the terrain renderer scene node: We add it just like any other scene node to the scene using ISceneManager::addTerrainSceneNode(). The only parameter we use is a file name to the heightmap we use. A heightmap is simply a gray scale texture. The terrain renderer loads it and creates the 3D terrain from it. To make the terrain look more big, we change the scale factor of it to (40, 4.4, 40). Because we don't have any dynamic lights in the scene, we switch off the lighting, and we set the file terrain-texture.jpg as texture for the terrain and detailmap3.jpg as second texture, called detail map. At last, we set the scale values for the texture: The first texture will be repeated only one time over the whole terrain, and the second one (detail map) 20 times. */ // add terrain scene node scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode( "../../media/terrain-heightmap.bmp", 0, // parent node -1, // node id core::vector3df(0.f, 0.f, 0.f), // position core::vector3df(0.f, 0.f, 0.f), // rotation core::vector3df(40.f, 4.4f, 40.f), // scale video::SColor ( 255, 255, 255, 255 ), // vertexColor 5, // maxLOD scene::ETPS_17, // patchSize 4 // smoothFactor ); if ( terrain ) { terrain->setMaterialFlag(video::EMF_LIGHTING, false); terrain->setMaterialTexture(0, driver->getTexture("../../media/terrain-texture.jpg")); terrain->setMaterialTexture(1, driver->getTexture("../../media/detailmap3.jpg")); terrain->setMaterialType(video::EMT_DETAIL_MAP); terrain->scaleTexture(1.0f, 20.0f); //terrain->setDebugDataVisible ( true ); /* To be able to do collision with the terrain, we create a triangle selector. If you want to know what triangle selectors do, just take a look into the collision tutorial. The terrain triangle selector works together with the terrain. To demonstrate this, we create a collision response animator and attach it to the camera, so that the camera will not be able to fly through the terrain. */ // create triangle selector for the terrain scene::ITriangleSelector* selector = smgr->createTerrainTriangleSelector(terrain, 0); terrain->setTriangleSelector(selector); // create collision response animator and attach it to the camera scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator( selector, camera, core::vector3df(60,100,60), core::vector3df(0,0,0), core::vector3df(0,50,0)); selector->drop(); camera->addAnimator(anim); anim->drop(); /* If you need access to the terrain data you can also do this directly via the following code fragment. */ scene::CDynamicMeshBuffer* buffer = new scene::CDynamicMeshBuffer(video::EVT_2TCOORDS, video::EIT_16BIT); terrain->getMeshBufferForLOD(*buffer, 0); video::S3DVertex2TCoords* data = (video::S3DVertex2TCoords*)buffer->getVertexBuffer().getData(); // Work on data or get the IndexBuffer with a similar call. buffer->drop(); // When done drop the buffer again. } /* To make the user be able to switch between normal and wireframe mode, we create an instance of the event reciever from above and let Irrlicht know about it. In addition, we add the skybox which we already used in lots of Irrlicht examples and a skydome, which is shown mutually exclusive with the skybox by pressing 'S'. */ // create skybox and skydome driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); scene::ISceneNode* skybox=smgr->addSkyBoxSceneNode( driver->getTexture("../../media/irrlicht2_up.jpg"), driver->getTexture("../../media/irrlicht2_dn.jpg"), driver->getTexture("../../media/irrlicht2_lf.jpg"), driver->getTexture("../../media/irrlicht2_rt.jpg"), driver->getTexture("../../media/irrlicht2_ft.jpg"), driver->getTexture("../../media/irrlicht2_bk.jpg")); scene::ISceneNode* skydome=smgr->addSkyDomeSceneNode(driver->getTexture("../../media/skydome.jpg"),16,8,0.95f,2.0f); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true); // create event receiver EventReceiver_terrain receiver( device, terrain, skybox, skydome); device->setEventReceiver(&receiver); return run ( device ); }
int main(int argc, char** argv) { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // create device and exit if creation failed IrrlichtDevice* device = createDevice(driverType, core::dimension2d<u32>(640, 480)); if (device == 0) return 1; // could not create selected driver. device->setWindowCaption(L"Load .irr file example"); video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); /* Now load our .irr file. .irr files can store the whole scene graph including animators, materials and particle systems. And there is also the possibility to store arbitrary user data for every scene node in that file. To keep this example simple, we are simply loading the scene here. See the documentation at ISceneManager::loadScene and ISceneManager::saveScene for more information. So to load and display a complicated huge scene, we only need a single call to loadScene(). */ // load the scene if (argc>1) smgr->loadScene(argv[1]); else smgr->loadScene("../../media/example.irr"); /* Now we'll create a camera, and give it a collision response animator that's built from the mesh nodes in the scene we just loaded. */ scene::ICameraSceneNode * camera = smgr->addCameraSceneNodeFPS(0, 50.f, 0.1f); // Create a meta triangle selector to hold several triangle selectors. scene::IMetaTriangleSelector * meta = smgr->createMetaTriangleSelector(); /* Now we will find all the nodes in the scene and create triangle selectors for all suitable nodes. Typically, you would want to make a more informed decision about which nodes to performs collision checks on; you could capture that information in the node name or Id. */ core::array<scene::ISceneNode *> nodes; smgr->getSceneNodesFromType(scene::ESNT_ANY, nodes); // Find all nodes for (u32 i=0; i < nodes.size(); ++i) { scene::ISceneNode * node = nodes[i]; scene::ITriangleSelector * selector = 0; switch(node->getType()) { case scene::ESNT_CUBE: case scene::ESNT_ANIMATED_MESH: // Because the selector won't animate with the mesh, // and is only being used for camera collision, we'll just use an approximate // bounding box instead of ((scene::IAnimatedMeshSceneNode*)node)->getMesh(0) selector = smgr->createTriangleSelectorFromBoundingBox(node); break; case scene::ESNT_MESH: case scene::ESNT_SPHERE: // Derived from IMeshSceneNode selector = smgr->createTriangleSelector(((scene::IMeshSceneNode*)node)->getMesh(), node); break; case scene::ESNT_TERRAIN: selector = smgr->createTerrainTriangleSelector((scene::ITerrainSceneNode*)node); break; case scene::ESNT_OCTREE: selector = smgr->createOctreeTriangleSelector(((scene::IMeshSceneNode*)node)->getMesh(), node); break; default: // Don't create a selector for this node type break; } if(selector) { // Add it to the meta selector, which will take a reference to it meta->addTriangleSelector(selector); // And drop my reference to it, so that the meta selector owns it. selector->drop(); } } /* Now that the mesh scene nodes have had triangle selectors created and added to the meta selector, create a collision response animator from that meta selector. */ scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator( meta, camera, core::vector3df(5,5,5), core::vector3df(0,0,0)); meta->drop(); // I'm done with the meta selector now camera->addAnimator(anim); anim->drop(); // I'm done with the animator now // And set the camera position so that it doesn't start off stuck in the geometry camera->setPosition(core::vector3df(0.f, 20.f, 0.f)); // Point the camera at the cube node, by finding the first node of type ESNT_CUBE scene::ISceneNode * cube = smgr->getSceneNodeFromType(scene::ESNT_CUBE); if(cube) camera->setTarget(cube->getAbsolutePosition()); /* That's it. Draw everything and finish as usual. */ int lastFPS = -1; while(device->run()) if (device->isWindowActive()) { driver->beginScene(true, true, video::SColor(0,200,200,200)); smgr->drawAll(); driver->endScene(); int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Load Irrlicht File example - Irrlicht Engine ["; str += driver->getName(); str += "] FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; } } device->drop(); return 0; }
static bool testOrthoCam(video::E_DRIVER_TYPE driverType) { IrrlichtDevice *device = createDevice (driverType, core::dimension2d<u32>(160,120)); if (!device) return true; // No error if device does not exist stabilizeScreenBackground(device->getVideoDriver()); scene::ICameraSceneNode* cam = device->getSceneManager()->addCameraSceneNode(); cam->setPosition(core::vector3df(500,200,-500)); cam->setTarget(core::vector3df()); cam->setProjectionMatrix(core::matrix4().buildProjectionMatrixOrthoLH(240,180,0.9f,2000.f,driverType != video::EDT_OPENGL), true); device->getSceneManager()->addAnimatedMeshSceneNode(device->getSceneManager()->addHillPlaneMesh("plane", core::dimension2df(32,32), core::dimension2du(16,16)));//->setMaterialFlag(video::EMF_WIREFRAME, true); device->getSceneManager()->addCubeSceneNode(20.f)->setPosition(core::vector3df(50,20,50)); device->getSceneManager()->addCubeSceneNode(20.f)->setPosition(core::vector3df(50,20,-50)); device->getSceneManager()->addCubeSceneNode(20.f)->setPosition(core::vector3df(50,50,0)); device->getSceneManager()->addCubeSceneNode(20.f)->setPosition(core::vector3df(-50,10,0)); device->getSceneManager()->addCubeSceneNode(20.f)->setPosition(core::vector3df(100,10,-100)); device->getSceneManager()->addCubeSceneNode(20.f)->setPosition(core::vector3df(150,10,0)); scene::IAnimatedMeshSceneNode* node = device->getSceneManager()->addAnimatedMeshSceneNode(device->getSceneManager()->getMesh("../media/ninja.b3d"), 0, -1, core::vector3df(-50,2,-50), core::vector3df(),core::vector3df(5,5,5)); node->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, true); node->setAnimationSpeed(0.f); scene::ILightSceneNode* light = device->getSceneManager()->addLightSceneNode(0, core::vector3df(0,100,0)); light->setLightType(video::ELT_POINT); light->setRadius(500.f); light->getLightData().DiffuseColor.set(0,1,1); device->getVideoDriver()->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(0,0,0,0)); device->getSceneManager()->drawAll(); device->getVideoDriver()->endScene(); const bool result = takeScreenshotAndCompareAgainstReference(device->getVideoDriver(), "-orthoCam.png", 99.91f); device->closeDevice(); device->run(); device->drop(); return result; }
static bool testLineRendering(video::E_DRIVER_TYPE type) { SIrrlichtCreationParameters params; params.AntiAlias = 2; params.Bits = 16; params.WindowSize = core::dimension2d<u32>(160, 120); params.DriverType = type; IrrlichtDevice *device = createDeviceEx(params); if (!device) return true; // in case the driver type does not exist video::IVideoDriver* driver = device->getVideoDriver(); // if no AntiAliasing supported, skip this test if (driver->getDriverAttributes().getAttributeAsInt("AntiAlias")<2) { device->closeDevice(); device->run(); device->drop(); return true; } logTestString("Testing driver %ls\n", driver->getName()); scene::ISceneManager* smgr = device->getSceneManager(); scene::IAnimatedMesh* mesh = smgr->getMesh("./media/sydney.md2"); if (!mesh) { device->closeDevice(); device->run(); device->drop(); return false; } stabilizeScreenBackground(driver); scene::IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh ); if (node) { node->setMaterialFlag(video::EMF_LIGHTING, false); node->setMD2Animation(scene::EMAT_STAND); node->setMaterialTexture( 0, driver->getTexture("./media/sydney.bmp") ); } smgr->addCameraSceneNode(0, core::vector3df(0,30,-40), core::vector3df(0,5,0)); device->getTimer()->setTime(0); // scene has animations and current scene seems to be saved at that time driver->beginScene(true, true, video::SColor(255,100,101,140)); smgr->drawAll(); driver->draw3DBox(node->getBoundingBox(), video::SColor(0,255,0,0)); driver->draw2DLine(core::position2di(10,10), core::position2di(100,100), video::SColor(255,0,0,0)); driver->endScene(); bool result = takeScreenshotAndCompareAgainstReference(driver, "-lineAntiAliasing.png", 99.4f ); device->closeDevice(); device->run(); device->drop(); return result; }
// Tests B3D animations. bool b3dAnimation(void) { // Use EDT_BURNINGSVIDEO since it is not dependent on (e.g.) OpenGL driver versions. IrrlichtDevice *device = createDevice( EDT_BURNINGSVIDEO, dimension2d<u32>(160, 120), 32); assert(device); if (!device) return false; IVideoDriver* driver = device->getVideoDriver(); ISceneManager * smgr = device->getSceneManager(); ISkinnedMesh* mesh = (ISkinnedMesh*)smgr->getMesh("../media/ninja.b3d"); assert(mesh); bool result = false; if (!mesh) return false; IAnimatedMeshSceneNode* node1 = smgr->addAnimatedMeshSceneNode(mesh); assert(node1); /** Verify that two skinned animated mesh scene nodes can use different frames of the skinned mesh */ if(node1) { node1->setPosition(vector3df(-3, -3, 10)); node1->setMaterialFlag(EMF_LIGHTING, false); node1->setAnimationSpeed(0.f); node1->setCurrentFrame(10.f); node1->setDebugDataVisible(irr::scene::EDS_BBOX_BUFFERS); } IAnimatedMeshSceneNode* node2 = smgr->addAnimatedMeshSceneNode(mesh); assert(node2); if(node2) { node2->setPosition(vector3df(3, -3, 10)); node2->setMaterialFlag(EMF_LIGHTING, false); node2->setAnimationSpeed(0.f); node2->setCurrentFrame(62.f); node2->setDebugDataVisible(irr::scene::EDS_BBOX_BUFFERS); } (void)smgr->addCameraSceneNode(); // Just jump to the last frame since that's all we're interested in. device->run(); driver->beginScene(true, true, SColor(255, 60, 60, 60)); smgr->drawAll(); driver->endScene(); result = takeScreenshotAndCompareAgainstReference(driver, "-b3dAnimation.png"); if (node2) node2->remove(); /** Now test if bones are correctly positioned. */ node1->setDebugDataVisible(scene::EDS_SKELETON); node1->setPosition(vector3df(1, -5, 8)); node1->setRotation(core::vector3df(0,180,0)); node1->updateAbsolutePosition(); for (u32 i=0; i<node1->getJointCount(); ++i) { smgr->addCubeSceneNode(1.f,0,-1,node1->getJointNode(i)->getAbsolutePosition()); // smgr->addCubeSceneNode(1.f,node1->getJointNode(i)); } // Simple render call device->run(); driver->beginScene(true, true, SColor(255, 60, 60, 60)); smgr->drawAll(); driver->endScene(); result &= takeScreenshotAndCompareAgainstReference(driver, "-b3dJointPosition.png"); device->closeDevice(); device->run(); device->drop(); return result; }