Windows Build

Everything related to the code /
Tout ce qui touche au code
User avatar
Cire
Moderator
Posts: 350
Joined: Tue Oct 31, 2006 5:59 pm
Location: Somewhere on Earth

Post by Cire » Thu Dec 14, 2006 8:54 pm

1st Draft of replacement code for configuration code, I dubbed this as TA3D_Config.cpp/h

First the .h

Code: Select all

#pragma once

namespace TA3D
{
	namespace UTILS
	{
		class cConfig
		{
		private:
			typedef struct m_Key
			{
				String KeyName;
				String KeyValue;

				m_Key()
				{
					KeyName = String( "" );
					KeyValue = String( "" );
				}
			};

			typedef std::vector< m_Key * > KeyList;
			typedef KeyList::iterator KeyItor;

			String		m_sConfigFile;
			KeyList		m_Keys;
			bool		m_Dirty;

			m_Key *GetKey( const String &KeyName );
			m_Key *GetOrCreateKey( const String &KeyName );
		public:
			cConfig( const String &FileName );
			~cConfig();

			bool EraseKey( const String &name );
			
			void SetKey( const String &name, const real32 v );
			void SetKey( const String &name, const real64 v );
			void SetKey( const String &name, const sint32 v );
			void SetKey( const String &name, const bool v );
			void SetKey( const String &name, const String &v );

			real32 KeyValueFloat( const String &name );
			real64 KeyValueDouble( const String &name );
			sint32 KeyValueInt( const String &name );
			bool   KeyValueBool( const String &name );
			String KeyValueString( const String &name );

			void SaveConfigFile();
			void ReadConfigFile();
		}; // class cConfig
	} // namespace UTILS
} // namespace TA3D
and the cpp

Code: Select all

#include "stdafx.h"
#include <sstream>
#include <iostream>
#include <fstream>
#include "TA3D_NameSpace.h"
#include "taconfig.h"

using namespace TA3D::UTILS;

cConfig::cConfig( const String &FileName ) : m_sConfigFile( FileName ) 
{ 
	m_Dirty = false; 
}
	
cConfig::~cConfig() 
{ 
	if( m_Dirty )
		SaveConfigFile();

	// cleanup
}

TA3D::UTILS::cConfig::m_Key *cConfig::GetKey( const String &KeyName )
{
	KeyItor k_Position;
	m_Key *Result = NULL;

	for( k_Position = this->m_Keys.begin(); k_Position != this->m_Keys.end(); k_Position++ )
	{
		if( (*k_Position)->KeyName == KeyName )
		{
			Result =(*k_Position);
			break;
		}
	}

	return Result;
}


TA3D::UTILS::cConfig::m_Key *cConfig::GetOrCreateKey( const String &KeyName )
{
	KeyItor k_Position;
	m_Key *Result = GetKey( KeyName );

	if( Result == NULL )
	{
		Result = new m_Key;
		Result->KeyName = KeyName;
	}

	return Result;
}

bool cConfig::EraseKey( const String &name )
{
	KeyItor k_Position;
	String KeyName = Lowercase( name );
	bool Result = false;

	for( k_Position = m_Keys.begin(); k_Position != m_Keys.end(); k_Position++ )
	{
		if( (*k_Position)->KeyName == KeyName )
		{
			m_Dirty = true;

			delete( *k_Position );

			m_Keys.erase( k_Position );

			Result = true;
			break;
		}
	}

	return Result;
}

void cConfig::SetKey( const String &name, const real32 v ) // float
{
	std::stringstream s;
	m_Key *Key = GetOrCreateKey( Lowercase( name ) );

	s<<v;
	Key->KeyValue=s.str();
	m_Dirty = true;
}

void cConfig::SetKey( const String &name, const real64 v ) // double
{
	std::stringstream s;
	m_Key *Key = GetOrCreateKey( Lowercase( name ) );

	s<<v;
	Key->KeyValue=s.str();
	m_Dirty = true;
}

void cConfig::SetKey( const String &name, const bool v ) // bool
{
	std::stringstream s;
	m_Key *Key = GetOrCreateKey( Lowercase( name ) );

	s<<( (v) ? "true" : "false" );
	Key->KeyValue=s.str();
	m_Dirty = true;
}

void cConfig::SetKey( const String &name, const sint32 v ) // signed int 32
{
	std::stringstream s;
	m_Key *Key = GetOrCreateKey( Lowercase( name ) );

	s<<v;
	Key->KeyValue=s.str();
	m_Dirty = true;
}

void cConfig::SetKey( const String &name, const String &v ) // string
{
	m_Key *Key = GetOrCreateKey( Lowercase( name ) );

	Key->KeyValue=String( v );
	m_Dirty = true;
}

real32 cConfig::KeyValueFloat( const String &name )
{
	m_Key *Key = GetKey( Lowercase( name ) );

	return ( (Key==NULL) ? 0.0f : (float)atof( Key->KeyValue.c_str() ) );
}

real64 cConfig::KeyValueDouble( const String &name )
{
	m_Key *Key = GetKey( Lowercase( name ) );

	return ( (Key==NULL) ? (double)0.0 : (double)atof( Key->KeyValue.c_str() ) );
}

sint32 cConfig::KeyValueInt( const String &name )
{
	m_Key *Key = GetKey( Lowercase( name ) );

	return ( (Key==NULL) ? 0 : (sint32)atoi( Key->KeyValue.c_str() ) );
}

bool cConfig::KeyValueBool( const String &name )
{
	m_Key *Key = GetKey( Lowercase( name ) );

	return ( (Key==NULL) ? false : Key->KeyValue=="true" );
}

String cConfig::KeyValueString( const String &name )
{
	m_Key *Key = GetKey( Lowercase( name ) );

	return ( (Key==NULL) ? "" : Key->KeyValue );
}

void cConfig::ReadConfigFile()
{
	std::ifstream file( m_sConfigFile.c_str(), ios::in );

	if( !file.is_open() ) return;

	String line, name, value;
	int posEqual;

	while ( !file.eof() )
	{
		std::getline( file, line, '\n' );

		if( !line.length() ) continue;
		if (line[0] == '#' || line[0] == ';' ) continue;

		if( (posEqual=(int)line.find( '=' )) != string::npos )
		{
			name  = TrimString( line.substr( 0,posEqual ) );
			value = TrimString( line.substr( posEqual+1 ) );

			m_Key *Key=GetOrCreateKey( Lowercase( name ) );
			Key->KeyValue = String( value );
		}
	}

	file.close();
}

void cConfig::SaveConfigFile()
{
	std::ofstream file( m_sConfigFile.c_str(), ios::out | ios::trunc );

	if( !file.is_open() ) return;

	KeyItor k_Position;

	for( k_Position = this->m_Keys.begin(); k_Position != this->m_Keys.end(); k_Position++ )
		file << (*k_Position)->KeyName << "=" << (*k_Position)->KeyValue << "\n";

	file.close();
}
This should be more then adquet to do the jpb however I want to bring it outa the 'legacy' state and const most functions as they can be cached thout probably not important.

I also need to add some comments to the code thou it should be pretty easy for most to follow. The std headers should also be moved into stdafx.h as other files will probably make use of them.

I move the translation code into its own files, and will post a rewrite of them tonight/tommorow.


Final draft of this code should be aviable by otnight which i'll also post.

++Cire.

User avatar
Cire
Moderator
Posts: 350
Joined: Tue Oct 31, 2006 5:59 pm
Location: Somewhere on Earth

Post by Cire » Fri Dec 15, 2006 1:30 am

Networking should NOT be priority, again you are jumping the gun.

I guess I need to be a bit criticle here as no one seems to be undering what needs to be done. Now many of you know that I have a storng background in C++/asm programing, but I have also worked as project manager, designer, and worked with a team both remote and local.

What i'am about to say should be taken as constructive critiism, and it should be taken to heart.

TA3D has alot of potentional, but it also has alot of pitfalls and issues that MUST be addressed NOW before the project begins to take off. Fire up TA3D, it runs well, take alittle while to load but load seuqneces can be optomized later. However start adding some units, the frame rate starts to drop pretty fast, once u start pushing 25 to 50 units frame rates have dropped by HUGE ammounts, so how can you even think about having multi-player support when the average game will have in excess of 200 or more units per side.

There are all kinds of areas within the engine that can be fixed and optomized, hell we just started making some by precalculating some variables (Screen width /2 ) for example, this don't sound like much but put on a whole this probably saved about 5 to 10 frames every 3 or 4 seconds. There are many many many more areas that could be optomized to fix this.

I've been working diligently at rewritting parts of the core lib starting and expanding inwards. We are not using C++ fully to its ability and thiere are alot of bad designs in TA3D. We do not use C++'s supperclasses which are ideal to RTS and especially the workings of TA.

The core of the player must be rewritten, What I mean by some of this is take a unit, it is composed of a script or cob, a 3do model, some textures, sounds, ect. Right now every part of a unit is stored speatly within different areas of code classes, this isn't how it should, intead we should have a simple class for loading sounds, a simple class for loading a model, a simple class for loading textures and so on, now for units themselves we derrive from those other classes to compose our unit as a supper class, so telling a unit to load will call to other recursive calls to all other classes its made up from which will completely load the entire unit. and even compose of functions to draw the unit.

So we have
Sound class
fbi class
3do class
ect...

our unit class is derrived from those other classes listed above
when we tell the unit to load itself it...
unit class::load()
sound::load()
fib::load()
3do::load()
ect..

it would also contain as i said additional functions to render itself, clean itself up, whatever else it needed.

The end result is neatly wrapped code that can also be easlly profiled and followed step by step to look for areas that might need addressed, its also easier to expand upon,work with, debug, ect, it reduces the 'crap' in the main engine brunt code, and so on.

These are just a few areas we should be looking at, as for multi-player i'am not saying stop developing on it, i'am saying we arn't ready for it, we should start with ai games first missions so to speak or skirimishes. with the exception of ai logic they can after all be though of as a 2 or more player game, except that an ai is makign decessions instead of another player.

++Cire.

User avatar
Balthazar
Moderator
Posts: 2055
Joined: Wed Nov 01, 2006 4:31 pm
Location: Russian Federation
Contact:

Post by Balthazar » Fri Dec 15, 2006 6:22 am

Very clear. Cire scores as always :)
Well, thinking of multiplayer and 70 fps with 10 units on my AMD 2600+, 1024 Mb Ram and GF6600 doesn`t sound very good. What will become if there`ll be at least 1000 units per player? A slide-show? We must optimize TA3D engine to run at maximum speed.

User avatar
zuzuf
Administrateur - Site Admin
Posts: 3281
Joined: Mon Oct 30, 2006 8:49 pm
Location: Toulouse, France
Contact:

Post by zuzuf » Fri Dec 15, 2006 6:59 pm

Of course we need to optimize things, but why should we use a supperclass? I noticed something when TA3D is running: it uses a big amount of bandwidth between CPU and memory. I reduced the size of the class that stores unit's data and the frame rate increased a lot. I think we should look at a it and try to reduce the bandwidth needs and also the algorithms complexity.

Of course networking isn't a priority but it will take time before we get a networking game running and we have someone who wants to do this part, so we can focus on optimizing the engine with assembly routines, reducing complexity, ...
=>;-D Penguin Powered

User avatar
Cire
Moderator
Posts: 350
Joined: Tue Oct 31, 2006 5:59 pm
Location: Somewhere on Earth

Post by Cire » Fri Dec 15, 2006 7:11 pm

Then your classes were not probably written, classes should reduce memory, in most cases, and in some cases increase it. However code should execute always faster unless there are instructions not handled, but this is where the profiler comes in handy.

Superclases improve design, flexability, debugging, and makes it easier to track down issues, and this is just a few improvements over regular function calls.

++Cire.

User avatar
Cire
Moderator
Posts: 350
Joined: Tue Oct 31, 2006 5:59 pm
Location: Somewhere on Earth

Post by Cire » Fri Dec 15, 2006 7:26 pm

The first step I think you should take imho, is to remove 'everything' that is player orianted to a class. with protected data to prevent bad code from screwing with what they shouln't.

Start to get into the habit of passing variables by const, and if possible const functions that are used alot, this is espeically imporant for caching to occur on key functions.

Don't think of a player as a 'user' but as a opponent in the game, they could be an ai, or a remote user, yes you should have away to tell the difference but they are still 1 in the same.

Now I seen you init players along the lines of metal[10] ect... you own't need this anymore instead track players in a vector, create a new player class when u need a new player and push them onto the vector stack This will make it easy for you to sync players with later, as you can simply orginize the vector how you see fit and index them via overloaded [] operators. Even better would be to have another class that is a 'players' class that would manage adding/removing players, as well as calling functions to message players, event invoke and so on, thus wrapping functions that affect player/s and so on.

Once we got this all wrapped up we need a functional ai, that should make skirmish matches doable between local user and an ai player(s). This will help us profile and step code looking for areas that should be addressed, right now we are pretty much shooting in the dark hoping to hit an area that is slow, profiling the code will give us a much more accurate picture. I have a very good profiler and can provide all the data we will need to target and address troublsome areas.

++Cire.

Post Reply

Who is online

Users browsing this forum: No registered users and 33 guests