Changeset 6424 in orxonox.OLD for trunk/src/story_entities/debug_world.cc
- Timestamp:
- Jan 7, 2006, 11:07:22 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/story_entities/debug_world.cc
r6222 r6424 1 /*2 orxonox - the future of 3D-vertical-scrollers3 4 Copyright (C) 2004 orx5 6 This program is free software; you can redistribute it and/or modify7 it under the terms of the GNU General Public License as published by8 the Free Software Foundation; either version 2, or (at your option)9 any later version.10 11 ### File Specific:12 main-programmer: Patrick Boenzli13 co-programmer: Christian Meyer14 co-programmer: Benjamin Grauer15 */16 17 #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD18 19 #include "world.h"20 21 #include "shell_command.h"22 23 #include "state.h"24 25 #include "p_node.h"26 #include "pilot_node.h"27 #include "world_entity.h"28 #include "player.h"29 #include "camera.h"30 #include "environment.h"31 #include "skysphere.h"32 #include "skybox.h"33 #include "satellite.h"34 #include "test_entity.h"35 #include "terrain.h"36 #include "light.h"37 #include "load_param.h"38 #include "shell.h"39 40 #include "fast_factory.h"41 #include "animation_player.h"42 #include "particle_engine.h"43 #include "graphics_engine.h"44 #include "physics_engine.h"45 #include "fields.h"46 47 #include "md2Model.h"48 49 #include "glmenu_imagescreen.h"50 #include "game_loader.h"51 52 #include "animation3d.h"53 54 #include "substring.h"55 56 #include "factory.h"57 58 #include "weapons/projectile.h"59 #include "event_handler.h"60 #include "sound_engine.h"61 #include "ogg_player.h"62 63 #include "class_list.h"64 65 #include "cd_engine.h"66 #include "npcs/npc_test1.h"67 #include "shader.h"68 69 #include "playable.h"70 #include "network_manager.h"71 #include "playable.h"72 73 74 SHELL_COMMAND(speed, World, setSpeed);75 SHELL_COMMAND(togglePNodeVisibility, World, togglePNodeVisibility);76 SHELL_COMMAND(toggleBVVisibility, World, toggleBVVisibility);77 78 using namespace std;79 80 //! This creates a Factory to fabricate a World81 CREATE_FACTORY(World, CL_WORLD);82 83 World::World(const TiXmlElement* root)84 {85 this->constuctorInit("", -1);86 this->path = NULL;87 88 this->loadParams(root);89 }90 91 /**92 * create a new World93 94 This creates a new empty world!95 */96 World::World (const char* name)97 {98 this->path = NULL;99 this->constuctorInit(name, -1);100 }101 102 /**103 * creates a new World...104 * @param worldID with this ID105 */106 World::World (int worldID)107 {108 this->path = NULL;109 this->constuctorInit(NULL, worldID);110 }111 112 /**113 * remove the World from memory114 115 delete everything explicitly, that isn't contained in the parenting tree!116 things contained in the tree are deleted automaticaly117 */118 World::~World ()119 {120 delete this->shell;121 PRINTF(3)("World::~World() - deleting current world\n");122 123 delete this->localPlayer;124 125 // delete all the initialized Engines.126 FastFactory::flushAll(true);127 delete LightManager::getInstance();128 delete ParticleEngine::getInstance();129 delete AnimationPlayer::getInstance();130 delete PhysicsEngine::getInstance();131 132 // external engines initialized by the orxonox-class get deleted133 SoundEngine::getInstance()->flushAllBuffers();134 SoundEngine::getInstance()->flushAllSources();135 136 if (State::getObjectManager() == &this->objectManager)137 State::setObjectManager(NULL);138 // erease everything that is left.139 delete PNode::getNullParent();140 141 //secondary cleanup of PNodes;142 const std::list<BaseObject*>* nodeList = ClassList::getList(CL_PARENT_NODE);143 if (nodeList != NULL)144 while (!nodeList->empty())145 delete nodeList->front();146 147 Shader::suspendShader();148 149 // unload the resources !!150 ResourceManager::getInstance()->unloadAllByPriority(RP_LEVEL);151 152 delete[] this->path;153 }154 155 /**156 * initializes the world.157 * @param name the name of the world158 * @param worldID the ID of this world159 *160 * set all stuff here that is world generic and does not use to much memory161 * because the real init() function StoryEntity::init() will be called162 * shortly before start of the game.163 * since all worlds are initiated/referenced before they will be started.164 * NO LEVEL LOADING HERE - NEVER!165 */166 void World::constuctorInit(const char* name, int worldID)167 {168 this->setClassID(CL_WORLD, "World");169 170 this->setName(name);171 this->debugWorldNr = worldID;172 this->gameTime = 0.0f;173 this->setSpeed(1.0);174 this->music = NULL;175 this->shell = NULL;176 this->localPlayer = NULL;177 this->localCamera = NULL;178 179 this->showPNodes = false;180 this->showBV = false;181 }182 183 /**184 * loads the parameters of a World from an XML-element185 * @param root the XML-element to load from186 */187 void World::loadParams(const TiXmlElement* root)188 {189 PRINTF(4)("Creating a World\n");190 191 LoadParam(root, "identifier", this, World, setStoryID)192 .describe("Sets the StoryID of this world");193 194 LoadParam(root, "nextid", this, World, setNextStoryID)195 .describe("Sets the ID of the next world");196 197 LoadParam(root, "path", this, World, setPath)198 .describe("The Filename of this World (relative from the data-dir)");199 }200 201 /**202 * this is executed just before load203 *204 * since the load function sometimes needs data, that has been initialized205 * before the load and after the proceeding storyentity has finished206 */207 ErrorMessage World::preLoad()208 {209 State::setObjectManager(&this->objectManager);210 this->cycle = 0;211 212 /* init the world interface */213 this->shell = new Shell();214 215 LightManager::getInstance();216 PNode::getNullParent();217 218 AnimationPlayer::getInstance(); // initializes the animationPlayer219 ParticleEngine::getInstance();220 PhysicsEngine::getInstance();221 222 this->localCamera = new Camera();223 this->localCamera->setName ("World-Camera");224 225 State::setCamera(this->localCamera, this->localCamera->getTarget());226 227 GraphicsEngine::getInstance()->displayFPS(true);228 }229 230 231 /**232 * loads the World by initializing all resources, and set their default values.233 */234 ErrorMessage World::load()235 {236 PRINTF(3)("> Loading world: '%s'\n", getPath());237 TiXmlElement* element;238 GameLoader* loader = GameLoader::getInstance();239 240 if( getPath() == NULL)241 {242 PRINTF(1)("World has no path specified for loading");243 this->loadDebugWorld(this->getStoryID());244 return (ErrorMessage){213,"Path not specified","World::load()"};245 }246 247 TiXmlDocument* XMLDoc = new TiXmlDocument( getPath());248 // load the campaign document249 if( !XMLDoc->LoadFile())250 {251 // report an error252 PRINTF(1)("loading XML File: %s @ %s:l%d:c%d\n", XMLDoc->ErrorDesc(), this->getPath(), XMLDoc->ErrorRow(), XMLDoc->ErrorCol());253 delete XMLDoc;254 return (ErrorMessage){213,"XML File parsing error","World::load()"};255 }256 257 // check basic validity258 TiXmlElement* root = XMLDoc->RootElement();259 assert( root != NULL);260 261 if( root == NULL || root->Value() == NULL || strcmp( root->Value(), "WorldDataFile"))262 {263 // report an error264 PRINTF(1)("Specified XML File is not an orxonox world data file (WorldDataFile element missing)\n");265 delete XMLDoc;266 return (ErrorMessage){213,"Path not a WorldDataFile","World::load()"};267 }268 269 // load the parameters270 // name271 const char* string = grabParameter( root, "name");272 if( string == NULL)273 {274 PRINTF(2)("World is missing a proper 'name'\n");275 this->setName("Unknown");276 }277 else278 {279 this->setName(string);280 }281 282 ////////////////283 // LOADSCREEN //284 ////////////////285 element = root->FirstChildElement("LoadScreen");286 if (element == NULL)287 {288 PRINTF(2)("no LoadScreen specified, loading default\n");289 290 glmis->setBackgroundImage("pictures/load_screen.jpg");291 this->glmis->setMaximum(8);292 this->glmis->draw();293 }294 else295 {296 this->glmis->loadParams(element);297 this->glmis->draw();298 }299 this->glmis->draw();300 301 ////////////////////////302 // find WorldEntities //303 ////////////////////////304 305 element = root->FirstChildElement("WorldEntities");306 307 if( element == NULL)308 {309 PRINTF(1)("World is missing 'WorldEntities'\n");310 }311 else312 {313 element = element->FirstChildElement();314 // load Players/Objects/Whatever315 PRINTF(4)("Loading WorldEntities\n");316 while( element != NULL)317 {318 BaseObject* created = Factory::fabricate(element);319 if( created != NULL )320 {321 if(created->isA(CL_WORLD_ENTITY))322 this->spawn(dynamic_cast<WorldEntity*>(created));323 printf("Created a %s: %s\n", created->getClassName(), created->getName());324 }325 326 // if we load a 'Player' we use it as localPlayer327 328 329 //todo do this more elegant330 if( element->Value() != NULL && !strcmp( element->Value(), "SkyBox"))331 sky = dynamic_cast<SkyBox*>(created);332 if( element->Value() != NULL && !strcmp( element->Value(), "Terrain"))333 {334 terrain = dynamic_cast<Terrain*>(created);335 CDEngine::getInstance()->setTerrain(terrain);336 }337 element = element->NextSiblingElement();338 glmis->step(); //! @todo temporary339 }340 PRINTF(4)("Done loading WorldEntities\n");341 }342 343 //////////////////////////////344 // LOADING ADDITIONAL STUFF //345 //////////////////////////////346 347 LoadParamXML(root, "LightManager", LightManager::getInstance(), LightManager, loadParams);348 349 LoadParamXML(root, "ParticleEngine", ParticleEngine::getInstance(), ParticleEngine, loadParams);350 // LoadParamXML(root, "PhysicsEngine", PhysicsEngine::getInstance(), PhysicsEngine, loadParams);351 352 // free the XML data353 354 delete XMLDoc;355 /* GENERIC LOADING PROCESS FINISHED */356 357 358 // Create a Player359 this->localPlayer = new Player();360 361 Playable* playable;362 const list<BaseObject*>* playableList = ClassList::getList(CL_PLAYABLE);363 if (playableList != NULL)364 {365 playable = dynamic_cast<Playable*>(playableList->front());366 this->localPlayer->setControllable(playable);367 }368 369 // bind camera370 playable->addChild (this->localCamera);371 372 // //localCamera->setParent(TrackNode::getInstance());373 // tn->addChild(this->localCamera);374 localCamera->setClipRegion(1, 10000.0);375 localCamera->lookAt(playable);376 // this->localPlayer->setParentMode(PNODE_ALL);377 if (sky != NULL)378 {379 this->sky->setParent(this->localCamera);380 this->sky->setParentMode(PNODE_MOVEMENT);381 }382 383 // initialize debug coord system384 objectList = glGenLists(1);385 glNewList (objectList, GL_COMPILE);386 387 glEndList();388 389 SoundEngine::getInstance()->setListener(this->localCamera);390 391 392 393 ////////////394 // STATIC //395 ////////////396 397 398 // TestEntity* testEntity = new TestEntity();399 // testEntity->setRelCoor(Vector(570, 10, -15));400 // testEntity->setRelDir(Quaternion(M_PI, Vector(0, 1, 0)));401 // this->spawn(testEntity);402 403 for(int i = 0; i < 100; i++)404 {405 WorldEntity* tmp = new NPCTest1();406 char npcChar[10];407 sprintf (npcChar, "NPC_%d", i);408 tmp->setName(npcChar);409 tmp->setAbsCoor(((float)rand()/RAND_MAX) * 5000, 50/*+ (float)rand()/RAND_MAX*20*/, ((float)rand()/RAND_MAX -.5) *30);410 this->spawn(tmp);411 }412 413 this->music = NULL;414 //(OggPlayer*)ResourceManager::getInstance()->load("sound/00-luke_grey_-_hypermode.ogg", OGG, RP_LEVEL);415 //music->playback();416 }417 418 419 420 /**421 * creates a debug world: only for experimental stuff422 */423 void World::loadDebugWorld(int worldID)424 {425 /*monitor progress*/426 this->glmis->step();427 // stuff beyond this point remains to be loaded properly428 429 // LIGHT initialisation430 LightManager::getInstance()->setAmbientColor(.1,.1,.1);431 // LightManager::getInstance()->addLight();432 LightManager::getInstance()->debug();433 434 switch(this->debugWorldNr)435 {436 /*437 this loads the hard-coded debug world. this only for simplicity and will be438 removed by a reald world-loader, which interprets a world-file.439 if you want to add an own debug world, just add a case DEBUG_WORLD_[nr] and440 make whatever you want...441 */442 case DEBUG_WORLD_0:443 {444 LightManager::getInstance()->getLight()->setAbsCoor(-5.0, 10.0, -40.0);445 /*monitor progress*/446 this->glmis->step();447 448 // bind camera449 this->localCamera = new Camera();450 this->localCamera->setName ("camera");451 /*monitor progress*/452 this->glmis->step();453 454 455 // Create SkySphere456 this->sky = new Skysphere("pictures/sky-replace.jpg");457 this->sky->setName("SkySphere");458 this->spawn(this->sky);459 this->localCamera->addChild(this->sky);460 this->sky->setParentMode(PNODE_MOVEMENT);461 /*monitor progress*/462 this->glmis->step();463 464 465 terrain = new Terrain("worlds/newGround.obj");466 terrain->setRelCoor(Vector(0,-10,0));467 this->spawn(terrain);468 /*monitor progress*/469 this->glmis->step();470 471 this->glmis->step();472 break;473 }474 case DEBUG_WORLD_1:475 {476 477 break;478 }479 case DEBUG_WORLD_2:480 {481 482 break;483 }484 default:485 break;486 }487 }488 489 /**490 * initializes a new World shortly before start491 *492 * this is the function, that will be loaded shortly before the world is493 * started494 */495 ErrorMessage World::init()496 {497 this->bPause = false;498 499 /* update the object position before game start - so there are no wrong coordinates used in the first processing */500 PNode::getNullParent()->updateNode (0.001f);501 PNode::getNullParent()->updateNode (0.001f);502 503 }504 505 506 /**507 * starts the World508 */509 ErrorMessage World::start()510 {511 PRINTF(3)("World::start() - starting current World: nr %i\n", this->debugWorldNr);512 this->bQuitOrxonox = false;513 this->bQuitCurrentGame = false;514 this->mainLoop();515 }516 517 /**518 * stops the world.519 520 This happens, when the player decides to end the Level.521 */522 ErrorMessage World::stop()523 {524 PRINTF(3)("World::stop() - got stop signal\n");525 this->bQuitCurrentGame = true;526 }527 528 /**529 * pauses the Game530 */531 ErrorMessage World::pause()532 {533 this->isPaused = true;534 }535 536 /**537 * ends the pause Phase538 */539 ErrorMessage World::resume()540 {541 this->isPaused = false;542 }543 544 /**545 * destroys the World546 */547 ErrorMessage World::destroy()548 {549 550 }551 552 /**553 * shows the loading screen554 */555 void World::displayLoadScreen ()556 {557 PRINTF(3)("World::displayLoadScreen - start\n");558 559 //GLMenuImageScreen*560 this->glmis = new GLMenuImageScreen();561 this->glmis->setMaximum(8);562 563 PRINTF(3)("World::displayLoadScreen - end\n");564 }565 566 /**567 * removes the loadscreen, and changes over to the game568 569 @todo take out the delay570 */571 void World::releaseLoadScreen ()572 {573 PRINTF(3)("World::releaseLoadScreen - start\n");574 this->glmis->setValue(this->glmis->getMaximum());575 PRINTF(3)("World::releaseLoadScreen - end\n");576 delete this->glmis;577 }578 579 580 /**581 * this returns the current game time582 * @returns elapsed game time583 */584 double World::getGameTime()585 {586 return this->gameTime;587 }588 589 /**590 \brief main loop of the world: executing all world relevant function591 592 in this loop we synchronize (if networked), handle input events, give the heart-beat to593 all other member-entities of the world (tick to player, enemies etc.), checking for594 collisions drawing everything to the screen.595 */596 void World::mainLoop()597 {598 this->lastFrame = SDL_GetTicks ();599 PRINTF(3)("World::mainLoop() - Entering main loop\n");600 601 while( !this->bQuitOrxonox && !this->bQuitCurrentGame) /* @todo implement pause */602 {603 ++this->cycle;604 // Network605 this->synchronize ();606 // Process input607 this->handleInput ();608 if( this->bQuitCurrentGame || this->bQuitOrxonox)609 break;610 // Process time611 this->tick ();612 // Process collision613 this->collide ();614 // Update the state615 this->update ();616 // Draw617 this->display ();618 }619 620 PRINTF(3)("World::mainLoop() - Exiting the main loop\n");621 }622 623 624 /**625 * synchronize local data with remote data626 */627 void World::synchronize ()628 {629 // Get remote input630 // Update synchronizables631 /* NetworkManager::getInstance()->synchronize();*/632 }633 634 635 /**636 * run all input processing637 638 the command node is the central input event dispatcher. the node uses the even-queue from639 sdl and has its own event-passing-queue.640 */641 void World::handleInput ()642 {643 EventHandler::getInstance()->process();644 645 // remoteinput646 }647 648 void World::tick(std::list<WorldEntity*> entityList, float dt)649 {650 std::list<WorldEntity*>::iterator entity;651 for (entity = entityList.begin(); entity != entityList.end(); entity++)652 (*entity)->tick(dt);653 654 }655 656 /**657 * advance the timeline658 659 this calculates the time used to process one frame (with all input handling, drawing, etc)660 the time is mesured in ms and passed to all world-entities and other classes that need661 a heart-beat.662 */663 void World::tick ()664 {665 Uint32 currentFrame = SDL_GetTicks();666 if(!this->bPause)667 {668 this->dt = currentFrame - this->lastFrame;669 670 if( this->dt > 10)671 {672 float fps = 1000/dt;673 674 // temporary, only for showing how fast the text-engine is675 char tmpChar[20];676 sprintf(tmpChar, "fps: %4.0f", fps);677 }678 else679 {680 /* the frame-rate is limited to 100 frames per second, all other things are for681 nothing.682 */683 PRINTF(3)("fps = 1000 - frame rate is adjusted\n");684 SDL_Delay(10-dt);685 this->dt = 10;686 }687 688 this->dtS = (float)this->dt / 1000.0 * this->speed;689 this->gameTime += this->dtS;690 691 /* this->tick(this->objectManager.getObjectList(OM_DEAD_TICK), this->dtS);692 this->tick(this->objectManager.getObjectList(OM_COMMON), this->dtS);693 this->tick(this->objectManager.getObjectList(OM_GROUP_00), this->dtS);*/694 this->tick(this->objectManager.getObjectList(OM_GROUP_01), this->dtS);695 this->tick(this->objectManager.getObjectList(OM_GROUP_01_PROJ), this->dtS);696 697 /* update tick the rest */698 this->localCamera->tick(this->dtS);699 // tick the engines700 AnimationPlayer::getInstance()->tick(this->dtS);701 // if (this->cycle > 5)702 PhysicsEngine::getInstance()->tick(this->dtS);703 704 ParticleEngine::getInstance()->tick(this->dtS);705 706 707 /** actualy the Graphics Engine should tick the world not the other way around...708 but since we like the things not too complicated we got it this way around709 until there is need or time to do it the other way around.710 @todo: GraphicsEngine ticks world: separation of processes and data...711 712 bensch: in my opinion the GraphicsEngine could draw the world, but not tick it,713 beceause graphics have nothing(or at least not much) to do with Motion.714 */715 GraphicsEngine::getInstance()->tick(this->dtS);716 }717 this->lastFrame = currentFrame;718 }719 720 721 /**722 * this function gives the world a consistant state723 724 after ticking (updating the world state) this will give a constistant725 state to the whole system.726 */727 void World::update()728 {729 GraphicsEngine::getInstance()->update(this->dtS);730 PNode::getNullParent()->updateNode (this->dtS);731 732 SoundEngine::getInstance()->update();733 //music->update();734 }735 736 737 void World::collide()738 {739 CDEngine::getInstance()->checkCollisions(this->objectManager.getObjectList(OM_GROUP_00),740 this->objectManager.getObjectList(OM_GROUP_01_PROJ));741 CDEngine::getInstance()->checkCollisions(this->objectManager.getObjectList(OM_GROUP_01),742 this->objectManager.getObjectList(OM_COMMON));743 }744 745 /**746 * render the current frame747 748 clear all buffers and draw the world749 */750 void World::display ()751 {752 // clear buffer753 glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);754 // set camera755 this->localCamera->apply ();756 // draw world757 this->draw();758 // draw HUD759 /** @todo draw HUD */760 // flip buffers761 GraphicsEngine::swapBuffers();762 //SDL_Surface* screen = Orxonox::getInstance()->getScreen ();763 //SDL_Flip (screen);764 }765 766 767 /**768 * runs through all entities calling their draw() methods769 */770 void World::draw ()771 {772 GraphicsEngine* engine = GraphicsEngine::getInstance();773 engine->draw(State::getObjectManager()->getObjectList(OM_ENVIRON_NOTICK));774 engine->draw(State::getObjectManager()->getObjectList(OM_ENVIRON));775 engine->draw(State::getObjectManager()->getObjectList(OM_COMMON));776 engine->draw(State::getObjectManager()->getObjectList(OM_GROUP_00));777 engine->draw(State::getObjectManager()->getObjectList(OM_GROUP_01));778 engine->draw(State::getObjectManager()->getObjectList(OM_GROUP_01_PROJ));779 780 // {781 // if( entity->isVisible() ) entity->draw();782 //FIXME783 // if( unlikely( this->showBV)) entity->drawBVTree(3, 226); // to draw the bounding boxes of the objects at level 2 for debug purp784 // entity = iterator->nextElement();785 // }786 787 glCallList (objectList);788 789 ParticleEngine::getInstance()->draw();790 791 if (unlikely(this->showPNodes))792 PNode::getNullParent()->debugDraw(0);793 794 engine->draw();795 //TextEngine::getInstance()->draw();796 }797 798 /**799 * add and spawn a new entity to this world800 * @param entity to be added801 */802 void World::spawn(WorldEntity* entity)803 {804 // this->entities->add (entity);805 entity->postSpawn ();806 }807 808 809 /**810 * add and spawn a new entity to this world811 * @param entity to be added812 * @param absCoor At what coordinates to add this entity.813 * @param absDir In which direction should it look.814 */815 void World::spawn(WorldEntity* entity, Vector* absCoor, Quaternion* absDir)816 {817 // this->entities->add (entity);818 819 entity->setAbsCoor (*absCoor);820 entity->setAbsDir (*absDir);821 822 entity->postSpawn ();823 }824 825 826 /**827 * add and spawn a new entity to this world828 * @param entity to be added829 * @param entity to be added to (PNode)830 * @param At what relative coordinates to add this entity.831 * @param In which relative direction should it look.832 */833 void World::spawn(WorldEntity* entity, PNode* parentNode,834 Vector* relCoor, Quaternion* relDir)835 {836 if( parentNode != NULL)837 {838 parentNode->addChild (entity);839 840 entity->setRelCoor (*relCoor);841 entity->setRelDir (*relDir);842 843 // this->entities->add (entity);844 845 entity->postSpawn ();846 }847 }848 849 void World::setPath( const char* name)850 {851 if (this->path)852 delete this->path;853 if (ResourceManager::isFile(name))854 {855 this->path = new char[strlen(name)+1];856 strcpy(this->path, name);857 }858 else859 {860 this->path = new char[strlen(ResourceManager::getInstance()->getDataDir()) + strlen(name) +1];861 sprintf(this->path, "%s%s", ResourceManager::getInstance()->getDataDir(), name);862 }863 }864 865 const char* World::getPath( void)866 {867 return path;868 }
Note: See TracChangeset
for help on using the changeset viewer.