Jump to content

  • Log In with Google      Sign In   
  • Create Account


Juliean

Member Since 29 Jun 2010
Offline Last Active Today, 04:18 PM

Posts I've Made

In Topic: c++ Performance boost needed

17 September 2014 - 03:15 PM


My question is: is the vector slowing my program down here, compared to using a simple array? I read somewhere, that the [] operator of the vector is defined as inline, and when it's called too often (fe. inside a loop), the compiler doesn't inline it and thus the access is slowed down. Is that right? I'm calling that function from inside a 0..1326 loop.

 

Vector is *almost* the same performance as a pure array - in release/optimized mode (debug mode at least in visual studio is horrible - vector can slow you down from 1000 to 8 FPS if you are not careful), since there happens almost no range checks, and most calls are inlined/optimized out.

 

I'm suprised operator[] is mentioned as being slow - actually, [] is faster than at() because [] does not perform range checks, at least for map-classes - at map, .at() will check if the index is valid, whereas [] will return a valid element eigther way, if the key didn't exist before, it will insert it. I assume it will behave similarily for vector too.

 

Anyways, for static arrays (int variables[256]), vector is quaranteed to be slower, since it requires at least an additional redirection. Don't use a vector here, eigther stick with pure arrays or use std::array, which is a new std container class for static arrays - vector is dynamic and therefore has certain overhead that doesn't exists for static arrays.


In Topic: Wrote an Entity-Component Framework

15 September 2014 - 04:14 PM


The information eventually ends up inside the base class of System. The reason I didn't want to do it through System's constructor was for three reasons:

  • It would force the user to write a constructor every time he derives from System just to pass in the necessary information.
  • Adding future options/more arguments to addSystem would cause every derived class' constructor to be re-written -> unnecessary.
  • addSystem() is more capable of making default decisions when arguments aren't supplied because the class it belongs to has access to all systems (such as execution reordering).

 

You don't have to use a constructor for this, but I would also advice towards keeping this information inside the system. You can have a virtual method in the system base class:

class System
{
public:

     virtual SupportedComponents GetSupportedComponents(void) const = 0;
}

every system will have to overwrite this and supply the components it wants to use. You can all this method e.g. directly inside "addSystem", which poses almost zero overhead but keeps this information in the systems declaration.


In Topic: std::unique_ptr issues

11 September 2014 - 03:29 AM

Alright, having the empty dtor AND and empty default ctor does the trick. That still makes things a little more ugly than I hoped too but well, its better than removing forward-declarations. Its not really a disadvantage, I would have had to define a ctor/dtor when using a raw pointer too, I was just hoping to get rid of them completely. Nevermind, I can work that way now, thanks to all.


In Topic: (Tower Defense) Template metaprogramming or Factory functions to avoid class...

09 September 2014 - 03:22 AM


Imagine if i have 50 tower in your enum, and a 50 case in the switch statement. Even worse, there could be like 200, or even 500 minion, with the same design. It's pretty hard to read and develop further. I think the programmer just loose himself easily in that.

 

As I said, thats the simpliest case. If you want to support more towers, use a config file like Krypt0n suggested. Templating does nothing really here, having 200 typedef is just as bad, if not even worse than such a switch statement. Having 200 different towers in code is going to suck, no matter what. Break out the common components - attacking, target selection, etc... and make those compositable via config files, again in the easiest case via a switch-statement, in the more complex case via a lexicon/registry.

 

Regarding further why templating is a bad idea: Range and Damage are stats/variables. Those are not something you template. They do not imply behaviour - their behaviour is dictated by the attack-component and probably some resistance-formula. Furthermore, you might want to adjust the attack based one e.g. a tower level or upgrade, and templates do not scale well with such things.


In Topic: (Tower Defense) Template metaprogramming or Factory functions to avoid class...

09 September 2014 - 02:59 AM

Why even have a templated/base class? Whats wrong with

class Tower
{
     Tower(int attack, float range);

private:

     int m_attack;
     float m_range;
}

And then instead of typedefing you could in the simpliest case use an enum and factory function:

enum class TowerType
{
    ARROW, MAGIC, BOMB
};

Tower& createTower(TowerType type)
{
    switch(type)
	{
	case TowerType::ARROW:
		return *new Tower(100, 50);
	case TowerType::MAGIC:
		return *new Tower(50, 100);
	case TowerType::BOMB:
		return *new Tower(300, 25);
	default:
		assert(false);
	}
}

And now for the attacking part, you can use composition, to derive different attack components:

class IAttack
{
	virtual void Attack() = 0;
}

class DefaultAttack : public IAttack
{
	void Attack() override;
};

class SplashAttack : public IAttack
{
	void Attack() override;
};

class SlowAttack : public IAttack
{
	void Attack() override;
};

Which you can then add to the tower class via dependency injection:

class Tower
{
     Tower(int attack, float range, IAttack& attack);

private:

     int m_attack;
     float m_range;
     IAttack* m_pAttack;
}

And your pretty much done. Now your tower can have a non-virtual "Attack"-method which calls the "components" virtual Attack(). You can (and probably will want to) grant access to the tower to the attack-component, eigther by adding "Tower& tower" to the IAttack::Attack()-method declaration, in which case you can share the attack-component with all towers that use the same type. Or you make another "IAttack::SetTower(Tower& tower)"-method and create a attacker-instance per tower.


PARTNERS