Index: orxonox/trunk/src/world.cc
===================================================================
--- orxonox/trunk/src/world.cc	(revision 2077)
+++ orxonox/trunk/src/world.cc	(revision 2190)
@@ -12,25 +12,14 @@
    ### File Specific:
    main-programmer: Patrick Boenzli
-   co-programmer:
-*/
-
-#include <iostream>
-#include <stdlib.h>
-#include <cmath>
-#include <GL/glut.h>
-
-#include "npc.h"
+   co-programmer: Christian Meyer
+*/
+
+#include "world.h"
+#include "world_entity.h"
+#include "collision.h"
+#include "track.h"
 #include "player.h"
-#include "environment.h"
-#include "shoot_laser.h"
-#include "shoot_rocket.h"
-#include "stdincl.h"
-#include "data_tank.h"
-
-#include "list.h"
-#include "world_entity.h"
-
-#include "world.h"
-
+#include "command_node.h"
+#include "camera.h"
 
 using namespace std;
@@ -38,461 +27,254 @@
 
 /** 
-   \brief Create a new World
+   \brief create a new World
    
-   This creates a new, empty world!
-*/
-World::World () {
-  //lastPlayer = null;
-  //lastNPC = null;
-  //lastEnv = null;
-  primitiveMove = 0;
-  step = 0;
-
-  //List<int> *list = new List<int>();
-  npcList = new List<WorldEntity*>();
-  playerList = new List<WorldEntity*>();
-  envList = new List<WorldEntity*>();
-}
-
-
-World::~World () {}
-
-
-
-/** 
-   \brief Load a new World
+   This creates a new empty world!
+*/
+World::World ()
+{
+	entities = new List<WorldEntity>();
+}
+
+/** 
+   \brief remove the World from memory
+*/
+World::~World ()
+{
+	unload ();
+	delete entities;
+}
+
+/** 
+   \brief checks for collisions
    
-   Load a new world. The old world (if any) will be unloaded and becomes unrecoverable. 
-*/
-void World::loadWorld() {}
-
-
-/** 
-   \brief Unloads a new World
+   This method runs through all WorldEntities known to the world and checks for collisions between them.
+   In case of collisions the collide() method of the corresponding entities is called.
+*/
+void World::collide ()
+{
+	List<WorldEntity> *a, *b;
+	WorldEntity *aobj, *bobj;
+	
+	a = entities->get_next();
+	
+	while( a != NULL)
+	{
+		aobj = a->get_object();
+		if( aobj->bCollide && aobj->collisioncluster != NULL)
+		{
+			b = a->get_next();
+			while( b != NULL)
+			{
+				bobj = b->get_object();
+				if( bobj->bCollide && bobj->collisioncluster != NULL)
+				{
+					unsigned long ahitflg, bhitflg;
+					if( check_collision ( &aobj->place, aobj->collisioncluster, &ahitflg, &bobj->place, bobj->collisioncluster, &bhitflg));
+					{
+						aobj->collide (bobj, ahitflg, bhitflg);
+						bobj->collide (aobj, bhitflg, ahitflg);
+					}
+				}
+				b = b->get_next();
+			}
+		}
+		a = a->get_next();
+	}
+}
+
+/** 
+   \brief runs through all entities calling their draw() methods
+*/
+void World::draw ()
+{
+	// draw geometry
+	
+	// draw entities
+	List<WorldEntity> *l;
+	WorldEntity* entity;
+	
+	l = entities->get_next();  
+	while( l != NULL) 
+	{ 
+		entity = l->get_object();
+	 	if(	entity->bDraw) entity->draw();
+	  l = l->get_next();
+	}
+	
+	// draw debug coord system
+	glLoadIdentity();
+	glBegin(GL_LINES);
+	for( float x = -128.0; x < 128.0; x += 25.0)
+	{
+		for( float y = -128.0; y < 128.0; y += 25.0)
+		{
+			glColor3f(1,0,0);
+			glVertex3f(x,y,-128.0);
+			glVertex3f(x,y,0.0);
+			glColor3f(0.5,0,0);
+			glVertex3f(x,y,0.0);
+			glVertex3f(x,y,128.0);
+		}
+	}
+	for( float y = -128.0; y < 128.0; y += 25.0)
+	{
+		for( float z = -128.0; z < 128.0; z += 25.0)
+		{
+			glColor3f(0,1,0);
+			glVertex3f(-128.0,y,z);
+			glVertex3f(0.0,y,z);
+			glColor3f(0,0.5,0);
+			glVertex3f(0.0,y,z);
+			glVertex3f(128.0,y,z);
+		}
+	}
+	for( float x = -128.0; x < 128.0; x += 25.0)
+	{
+		for( float z = -128.0; z < 128.0; z += 25.0)
+		{
+			glColor3f(0,0,1);
+			glVertex3f(x,-128.0,z);
+			glVertex3f(x,0.0,z);
+			glColor3f(0,0,0.5);
+			glVertex3f(x,0.0,z);
+			glVertex3f(x,128.0,z);
+		}
+	}
+	//draw track
+	glColor3f(0,1,1);
+	for( int i = 0; i < tracklen; i++)
+	{
+		glVertex3f(pathnodes[i].x,pathnodes[i].y,pathnodes[i].z);
+		glVertex3f(pathnodes[(i+1)%tracklen].x,pathnodes[(i+1)%tracklen].y,pathnodes[(i+1)%tracklen].z);
+	}
+	glEnd();
+}
+
+/** 
+   \brief updates Placements and notifies entities when they left the world
    
-   Unloads a world and frees the memory. You cant game until you have a new world loaded.
-*/
-void World::unloadWorld() {}
-
-
-/** 
-   \brief Pause the game
-   
-   Pauses the game until the pause is released. During this time nothing moves at all and nothing is calculated. Use it if you have to go out of the game to read some mails...
-*/
-void World::pauseWorld() {}
-
-
-/** 
-   \brief Save the game to file
-   \param filename: the filename where the savegame should be saved to
-   
-   Saves the state of the game to a file. The state is catched like in a multiplayer game over a synchronisable interface.
-*/
-void World::saveGameState(char* filename) {}
-
-
-
-/** 
-   \brief Add Player
-   \param player A reference to the new player object
-   
-   Add a new Player to the game. Player has to be initialised previously 
-*/
-bool World::addPlayer(Player* player) 
-{
-  WorldEntity *we;
-  playerList->add(we);
-  /*
-  playerList* listMember = new playerList;
-  listMember->player = player;
-  if ( lastPlayer != null ) 
-    {
-      listMember->number = lastPlayer->number + 1;
-      listMember->next = lastPlayer;
-    }
-  else 
-    {
-      listMember->number = 0;
-      listMember->next = null;
-    }
-  lastPlayer = listMember;
-  */
-}
-
-/** 
-   \brief Remove Player
-   \param player A reference to the new npc object
-   
-   Remove a new Player to the game. This kills the player objects.
-*/
-bool World::removePlayer(Player* player) {
-  playerList->remove(player, LIST_FIND_BW);
-}
-
-/** 
-   \brief Returns the player-entity controlled by the local gamer
-   \return pointer to player object
-   
-   Remove a new Player to the game. This kills the player objects.
-*/
-Player* World::getLocalPlayer() 
-{
-  return localPlayer;
-}
-
-
-/** 
-   \brief Add Non-Player-Character
-   \param player A reference to the new npc object
-   
-   Add a new Non-Player-Character to the game. Player has to be initialised previously 
-*/
-bool World::addNPC(NPC* npc) 
-{
-  npcList->add(npc, LIST_ADD_NEXT);
-  /*
-  npcList* listMember = new npcList;
-  listMember->npc = npc;
-  if ( lastNPC != null ) 
-    {
-      listMember->number = lastNPC->number + 1;
-      listMember->next = lastNPC;
-    }
-  else 
-    {
-      listMember->number = 0;
-      listMember->next = null;
-    }
-  lastNPC = listMember;
-  */
-}
-
-
-/** 
-   \brief Remove Non-Player Character
-   \param player A reference to the npc object
-   
-   Remove a Non-Player-Character to the game.
-*/
-bool World::removeNPC(NPC* npc) 
-{
-  npcList->remove(npc, LIST_FIND_FW);
-  /*
-  npcList* npcRef = lastNPC;
-  npcList* lastRef = lastNPC;
-  while ( npcRef != null ) 
-    {
-      if ( npcRef->npc == npc ) {
-	cout <
-< "found" << endl;
-	if ( npcRef == lastRef ) {
-	  lastNPC = lastNPC->next;
-	  delete npcRef;
-	  npcRef = lastNPC;
-	  lastRef = lastNPC;
-	}
-	else {
-	  lastRef->next = npcRef->next;
-	  delete npcRef;
-	  npcRef = lastRef->next;
-	}
-	cout << "killed ..." << endl;
-      }
-      else {
-	lastRef = npcRef;
-	npcRef = npcRef->next;
-      }
-    }
-  cout << "npc left" << endl;
-  */
-}
-
-
-
-/** 
-   \brief Add environmental object
-   \param player A reference to the new env object
-   
-   Add a new Environment to the world. Env has to be initialised before.
-*/
-bool World::addEnv(Environment* env) 
-{
-  /*
-  envList* listMember = new envList;
-  listMember->env = env;
-  if ( lastEnv != null ) 
-    {
-      listMember->number = lastEnv->number + 1;
-      listMember->next = lastEnv;
-    }
-  else 
-    {
-      listMember->number = 0;
-      listMember->next = null;
-    }
-  lastEnv = listMember;
-  */
-}
-
-/** 
-   \brief Remove an environmental object
-   \param player A reference to the env object
-   
-   Remove a environment from the game.
-*/
-bool World::removeEnv(Environment* env) 
-{
+   This runs trough all WorldEntities and maps Locations to Placements if they are bound, checks
+   whether they left the level boundaries and calls appropriate functions.
+*/
+void World::update ()
+{
+	List<WorldEntity> *l;
+	WorldEntity* entity;
+	Location* loc;
+	Placement* plc;
+	Uint32 t;
+	
+	l = entities->get_next();  
+	while( l != NULL) 
+	{ 
+		entity = l->get_object();
+		
+		if( !entity->isFree())
+		{
+		 	loc = entity->get_location();
+		 	plc = entity->get_placement();
+		 	t = loc->part;
+		 	
+		 	if( t >= tracklen)
+		 	{
+		 		printf("An entity is out of the game area\n");
+				entity->left_world ();
+		 	}
+		 	else
+		 	{
+		 		while( track[t].map_coords( loc, plc))
+		 		{
+		 			track[t].post_leave (entity);
+		 			if( loc->part >= tracklen)
+		 			{
+		 				printf("An entity has left the game area\n");
+		 				entity->left_world ();
+		 				break;
+		 			}
+		 			track[loc->part].post_enter (entity);
+		 		}
+		 	}
+		}
+		else
+		{
+			// TO DO: implement check whether this particular free entity is out of the game area
+			// TO DO: call function to notify the entity that it left the game area
+		}
+	 	
+	  l = l->get_next();
+	}
+	
+}
+
+/** 
+  \brief relays the passed time since the last frame to entities and Track parts
+	\param deltaT: the time passed since the last frame in milliseconds
+*/
+void World::time_slice (Uint32 deltaT)
+{
+	List<WorldEntity> *l;
+	WorldEntity* entity;
+	float seconds = deltaT;
+	
+	seconds /= 1000;
+	
+	l = entities->get_next();  
+	while( l != NULL) 
+	{ 
+		entity = l->get_object();
+	 	entity->tick (seconds);
+	  l = l->get_next();
+	}
+	
+	for( int i = 0; i < tracklen; i++) track[i].tick (seconds);
+}
+
+/**
+	\brief removes level data from memory
+*/
+void World::unload()
+{
+	if( pathnodes) delete []pathnodes;
+	if( track) delete []pathnodes;
+}
+
+/**
+	\brief loads a simple level for testing purposes
+*/
+void World::load_debug_level()
+{
+	// create some path nodes
+	pathnodes = new Vector[6];
+	pathnodes[0] = Vector(0, 0, 0);
+	pathnodes[1] = Vector(-100, 40, 0);
+	pathnodes[2] = Vector(-100, 140, 0);
+	pathnodes[3] = Vector(0, 180, 0);
+	pathnodes[4] = Vector(100, 140, 0);
+	pathnodes[5] = Vector(100, 40, 0);	
+	
+	// create the tracks
+	tracklen = 6;
+	track = new Track[6];
+	for( int i = 0; i < tracklen; i++)
+	{
+		track[i] = Track( i, (i+1)%tracklen, &pathnodes[i], &pathnodes[(i+1)%tracklen]);
+	}
+	
+	// create a player
+	WorldEntity* myPlayer = (WorldEntity*) spawn<Player>();
+	
+	// bind input
+  Orxonox *orx = Orxonox::getInstance();
+  orx->get_localinput()->bind (myPlayer);
   
-}
-
-
-
-
-/** 
-   \brief Draws the World and all Objects contained
-   
-   Calls the draw function of all: Objects, Players, Environement. This is the core of all graphics here.
-*/
-void World::drawWorld(void) 
-{
-
-  glLoadIdentity();
-  gluLookAt(0.0, -14.0 + DataTank::yOffset, 15.0, 0.0, 0.0 + DataTank::yOffset, 0.0, 0.0, 1.0, 0.0);
-  /* first draw all players */
-
-
-  /*
-  playerList* tmpPlayer = lastPlayer;
-  Player* player = tmpPlayer->player;
-  while( tmpPlayer != null ) 
-    {
-      tmpPlayer->player->paint();
-      tmpPlayer = tmpPlayer->next;
-    }
-  */
-  /* second draw all npcs */
-  /*
-  npcList* tmpNPC = lastNPC;
-  while( tmpNPC != null )
-    {
-      (*tmpNPC->npc).paint();
-      tmpNPC = tmpNPC->next;
-    }
-  */
-
-  /* now draw the rest of the world: environement */
-  /*
-  envList* tmpEnv = lastEnv;
-  while( tmpEnv != null )
-    {
-      (*tmpEnv->env).drawEnvironment();
-      tmpEnv = tmpEnv->next;
-    }
-  */
-
-  /* draw the ground grid  */
-  glColor3f(0.0, 1.0, 0.0); 
-  glBegin(GL_LINES);
-  /* for the moment, we've got only pseudo moving ground */
-  for (int y = 0; y < 60; y += 2)
-    {
-      for (int x = 0; x < 60; x += 2)
-	{
-	  glVertex3f((float)(x - 30), (float)(y - 30), surface[x][y]);
-	  glVertex3f((float)(x - 28), (float)(y - 30), surface[x+2][y]);
-	}
-    }
-  glEnd();
-  
-  glBegin(GL_LINES);
-  for (int x = 0; x < 60; x += 2)
-    {
-      for (int y = 0; y < 60; y += 2)
-	{
-	  glVertex3f((float)(x - 30), (float)(y - 30), surface[x][y]);
-	  glVertex3f((float)(x - 30), (float)(y - 28), surface[x][y+2]);
-	}
-    }
-  glEnd();
-
-  //primitiveMove+=0.07;
-  DataTank::yOffset += step;
-
-  /*
-  tmpPlayer = lastPlayer;
-  while( tmpPlayer != null ) 
-    {
-      tmpPlayer->player->yCor += step;
-      tmpPlayer = tmpPlayer->next;
-    }
-  */
-
-}
-
-
-void World::initEnvironement()
-{
-
- for (int x = 0; x < 60; x += 2)
-    {
-      for (int y = 0; y < 60; y += 2)
-	{
-	  surface[x][y] = 0;
-	}
-    }
-}
-
-
-void World::setWorldStep(float step)
-{
-  //cout << "World::setWorldStep(" << step << ");" << endl;
-  this->step = step;
-  //cout << "setting speed to " << step << endl;
-}
-
-
-
-/** 
-   \brief Updates the world and all its objects
-   
-   Calculates the new state of the world. User-input and AI of
-   the enemies are accounted for.
-*/
-void World::updateWorld(void) 
-{
-  
-
-}
-
-
-/* collision detection */
-/* fix: bad efficency: stupid brute force */
-
-void World::detectCollision() 
-{
-  /*
-  //cout << "World::detectCollision" << endl;
-  float xOff, yOff, zOff, radius;
-  npcList* tmpNPC, *tmpRef;
-  */
-  //cout << "World::detectCollsions" << endl;
-  /* first: check if any player's shoots trigger a collision */
-  /*
-  playerList* tmpPlayer = lastPlayer;
-  Player* player = tmpPlayer->player;
-  int state;
-  while( tmpPlayer != null ) 
-    {
-      tmpNPC = lastNPC;
-      while( tmpNPC != null )
-	{
-	  //cout << "npc != null" << endl;
-	  radius = tmpNPC->npc->collisionRadius;
-	  //cout << "worki" << endl;
-	  ShootLaser::shoot* shoota = tmpPlayer->player->shootLaser->lastShoot;
-	  while( shoota != null )
-	    {
-	      xOff = shoota->xCor - tmpNPC->npc->xCor;
-	      yOff = shoota->yCor - tmpNPC->npc->yCor;
-	      zOff = shoota->zCor - tmpNPC->npc->zCor;
-	      if ( sqrt(xOff*xOff + yOff*yOff + zOff*zOff) < radius ) 
-		{
-		  //cout << "COLLISION " << endl;
-		  int state = tmpNPC->npc->hit();
-  */
-		  /* state is a value that marks if the ship dies or not */
-		  /* if state == 0 the ship dies and we have to remove it */
-		  /*
-		  if ( state == 0 ) {
-		    tmpRef = tmpNPC;
-		    tmpNPC = tmpNPC->next;
-		    removeNPC(tmpRef->npc);
-		    break;
-		  }
-		  
-		}
-	      shoota = shoota->next;
-	    }
-	  //cout << "changing npc..." << endl;
-	  tmpNPC = tmpNPC->next;
-	  //cout << "..changing npc done" << endl;
-	}
-      //cout << "changing play..." << endl;
-      tmpPlayer = tmpPlayer->next;
-      //cout << "changing play done" << endl;
-      
-    }
-		  */
-  //cout << "World::detectCollisions middle" << endl;
-
-  /* second: check if any player hits an enemy */
-/*
-  tmpPlayer = lastPlayer;
-  while( tmpPlayer != null ) 
-    {
-      tmpNPC = lastNPC;
-      while( tmpNPC != null )
-	{
- 	  radius = tmpNPC->npc->collisionRadius + tmpPlayer->player->collisionRadius;
-	  xOff = tmpPlayer->player->xCor - tmpNPC->npc->xCor;
-	  yOff = tmpPlayer->player->yCor - tmpNPC->npc->yCor;
-	  zOff = tmpPlayer->player->zCor - tmpNPC->npc->zCor;
-	  if ( sqrt(xOff*xOff + yOff*yOff + zOff*zOff) < radius ) {
-	    //cout << "COLLISION " << endl;
-	    tmpNPC->npc->hit();
-	  }
-	  
-	  tmpNPC = tmpNPC->next;
-	}
-      
-      tmpPlayer = tmpPlayer->next;
-    }
-  
-  
-*/
-  /* third: check if any enemy shoots a player */
-
-  //cout << "World::detectCollisions end" << endl;
-}
-
-
-
-/** 
-   \brief Routine for testing purposes.
-   
-   testing, testing, testing...
-*/
-void World::testThaTest(void) 
-{
-/*
-  cout << "World::testThaTest() called" << endl;
-
-  cout << "addPlayer test..." << endl;
-  playerList* pl = lastPlayer;
-  while ( pl != null )
-    {
-      cout << "player " << pl->number << " was found" << endl;
-      pl = pl->next;
-    }
-
-
-  cout << "addNPC test..." << endl;
-  npcList* nl = lastNPC;
-  while ( nl != null )
-    {
-      cout << "npc " << nl->number << " was found" << endl;
-      nl = nl->next;
-    }
-
-
-
-  cout << "addEnv test..." << endl;
-  envList* en = lastEnv;
-  while ( en != null )
-    {
-      cout << "env " << en->number << " was found" << endl;
-      en = en->next;
-    }
-*/
-}
+	// bind camera
+	orx->get_camera()->bind (myPlayer);
+}
+
+/**
+	\brief calls the correct mapping function to convert a given "look at"-Location to a Camera Placement
+*/
+void World::calc_camera_pos (Location* loc, Placement* plc)
+{
+  track[loc->part].map_camera (loc, plc);
+}
