Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Re:creation - a top down action adventure about undeads [hiatus]  (Read 157209 times)

0 Members and 2 Guests are viewing this topic.

nebula

  • Jr. Member
  • **
  • Posts: 96
    • View Profile
    • Email
Re:creation - a top down action rpg about undeads
« Reply #195 on: August 29, 2015, 04:02:49 pm »
Dude this is awesome work.
Really like what you did there!

Keep it up ;-)

Elias Daler

  • Hero Member
  • *****
  • Posts: 570
    • View Profile
    • Blog
    • Email
Re:creation - a top down action rpg about undeads
« Reply #196 on: September 01, 2015, 08:36:03 am »
I found it interesting. It's comforting to know how often people change their minds during development!
Still, think of how far along the game would be now if you'd've put all the time into the game development instead of drawing new graphics  ;D

Yeah, I like to look at the progress albums for the same reason. (And it's also pretty interesting to look at my game's progress too! :D)
Yep, the game would be a lot larger and more developed. But think how far along it would be if I worked on it full time? Or if I didn't spend so much time posting about my progress/reading some stuff on reddit/etc.?
There's a lot of reasons for a game taking long to develop. Doing art for yourself is just one of them. And previously I didn't like it (even hated it sometimes). But now I'm pretty okay with that, lots of times I even have lots of fun drawing art. I've just accepted as a fact that finding an artist who's willing to work for revenue share is almost impossible, so all I can do for now is to deal with it! :D

@nebula, thanks!

Progress update
Finally I've figured out the way to store components continuosly in memory. It may not give the significant speed up (but I'll post the results of testing!) but it will be very helpful for the future. (And for other games I'll work on using the same engine).

I'm still working on this, but I will post the source code soon (probably this month) so people can use it for their own games. I would also love for people to propose some ideas about how I can make this system better.
Note that I won't post the source code of my engine. It's a completely separate prototype project with some tests but it would show most of the stuff I'll integrate into the game later.

The main principle is what someone later proposed in this thread.

I have this class:

class IComponentList {
...
};

and this class:

template <typename T>
class ComponentList : public IComponentList {
...
private:
    std::vector<T> components;
}

and then this map:

std::map<std::type_index, IComponentList*> componentLists

where key is std::type_index is std::type_index(typeid(T)) where T is a type of the component a corresponding value (a component list) holds.

I can currently get the list I need like this:

auto& list = ComponentManager::getInstance().getComponentList<SomeComponentType>();
 
The entity class interface remains the same, though. I still have:

class Entity {
...
    std::vector<Component*> components;
}

But now the entity points to components inside the component lists.
This is harder to implement than it looks, because:

1) Changing the position of a component in a component array invalidates the pointer in Entity so I have to change it manually
2) If I insert some new components in some vector L and the size of the vector is more than it's capacity, it will reallocate which means that every component pointer (of component type which L holds) in every entity becomes invalid.

This is not a big problem, though!

The first problem is easily solvable. The second is a bit harder, though.
I can fix it by reserving enough memory for each component vector so it won't reallocate again when the game is running (vectors would need to change it's sizes during level load but this is not critical, changing some pointers is not that hard during that.)
How can I know how much components of each type there will be? Easy. I have a list of every entity on the level in a level file which means that  I can count how much of each component time I would need.
What about entities which could previously create entities when the game was running (like bows which created arrow entities). I won't do this anymore! Allocating memory on when the game is running is bad anyway.
So, each entity can explicitly show that it can create new entities and each component list would get additional size to allocate.
For example, you won't see more than 1-2 arrows flying from the same bow on the screen. This means that I can reuse the same arrow entity over and over again. I will create arrow entity for each bow entity when the level loads and there's no need to create entities during gameplay anymore.
So, those limitations lead to some great improvements of other things! There are more aspects which I'll cover later.

P.S. Anyone knows any good articles about C++ templates? Especially about header dependency aspect of it. I want to make templates the way that they won't cause more recompilation then necessary (this is very easy to make if you're not careful).
Tomb Painter, Re:creation dev | eliasdaler.github.io | @EliasDaler | Tomb Painter dev log

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re:creation - a top down action rpg about undeads
« Reply #197 on: September 01, 2015, 09:06:39 am »
P.S. Anyone knows any good articles about C++ templates? Especially about header dependency aspect of it. I want to make templates the way that they won't cause more recompilation then necessary (this is very easy to make if you're not careful).
Using 'extern template's can help a great deal with that often. See this: http://en.cppreference.com/w/cpp/language/class_template (the section about "Explicit Instantiation")

Hapax

  • Hero Member
  • *****
  • Posts: 2706
  • My number of posts is shown in hexadecimal.
    • View Profile
Re:creation - a top down action rpg about undeads
« Reply #198 on: September 01, 2015, 10:22:36 pm »
But think how far along it would be if...
I didn't mean to suggest that it is progressing slowly. I'm sorry if it came across that way.
I think it's coming along great and I find its progress fascinating  :)
Selba Ward - SFML drawables
Kairos - Timing Library
Rectangular Boundary Collision - Rectangular SAT Collision

@Hapaxiation - Hapaxia on Twitter

Elias Daler

  • Hero Member
  • *****
  • Posts: 570
    • View Profile
    • Blog
    • Email
Re:creation - a top down action rpg about undeads
« Reply #199 on: September 01, 2015, 11:17:47 pm »
@Jesper Juhl, thanks. I've read the article but don't have an idea how to use this effectively (probably because I don't know some stuff about templates and header dependency). Can you provide any useful examples of using extern template in my case?

@Hapax, no offence taken.
Thanks, glad you like the progress :)
Tomb Painter, Re:creation dev | eliasdaler.github.io | @EliasDaler | Tomb Painter dev log

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6158
  • Thor Developer
    • View Profile
    • Bromeon
Re:creation - a top down action rpg about undeads
« Reply #200 on: September 01, 2015, 11:22:52 pm »
Quote from: Elias Daler
What about entities which could previously create entities when the game was running (like bows which created arrow entities). I won't do this anymore! Allocating memory on when the game is running is bad anyway.
A static pool wastes lots of memory and is a really bad idea. Unless you have really low memory requirements, I wouldn't go this way out of lazyness to implement a proper solution ;)

Quote from: Elias Daler
P.S. Anyone knows any good articles about C++ templates? Especially about header dependency aspect of it. I want to make templates the way that they won't cause more recompilation then necessary (this is very easy to make if you're not careful).
Explicit instantiation (see Jesper's post) and type erasure/PImpl are the most promising approaches, but they can only be applied in special cases.

Unfortunately, in most cases you simply don't have another option than keeping templates in the headers. Still, try at least to outsource parts that aren't dependent on template parameters, and avoid too deep dependencies... Sometimes it's worth trading off compile-time type safety for less code bloat and compilation time.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development: first SFML book

Elias Daler

  • Hero Member
  • *****
  • Posts: 570
    • View Profile
    • Blog
    • Email
Re:creation - a top down action rpg about undeads
« Reply #201 on: September 02, 2015, 06:58:07 am »
@Nexus, most additional entities (arrows, bombs, etc.) would be pretty lightweight compared to big ones. For example, one arrow contains GraphicsComponent (sf::Sprite which shares sf::Texture with other arrows) and CollisionComponent (two pointers and one sf::FloatRect).
What's the better way of doing this instead of using object pools? I have one idea: I can still benifit from creating object pool of size which all entities on the level reqiure (I need to load them all anyway). Then I can create additional component lists for entities which may be created during gameplay. When some of these lists need to expand, I would manually swap the pointers after reallocation which won't invalidate the pointers of components stored in a bigger vector (which was used for all entities on the level).

Unfortunately, in most cases you simply don't have another option than keeping templates in the headers. Still, try at least to outsource parts that aren't dependent on template parameters, and avoid too deep dependencies... Sometimes it's worth trading off compile-time type safety for less code bloat and compilation time.
I guess I just don't get how dependant some files become from each other if I use templates.
For example, I have a createComponent<T> free function in ComponentManager.h
If I change some stuff about components for which this template function is created, would this cause ComponentManager.h to recompile too?
Tomb Painter, Re:creation dev | eliasdaler.github.io | @EliasDaler | Tomb Painter dev log

Elias Daler

  • Hero Member
  • *****
  • Posts: 570
    • View Profile
    • Blog
    • Email
Re:creation - a top down action rpg about undeads
« Reply #202 on: September 03, 2015, 08:01:06 pm »
Small progress update.
Still working on new ECS implementation. Improvements are quite nice. (Sorry, no pretty pictures, working on code)

Suppose I have two entity types:

ghost = GraphicsComponent
tree = GraphicsComponent + CollisionComponent

What if I need to create 4 ghosts and 10 trees? I need to create 14 GraphicsComponent's and 10 CollisionComponent's.
But, simply adding them via push_back to std::vector of GraphicsComponent and CollisionComponent is a bad idea. Why? Because vector will reallocate it's memory array several times invalidating all pointers to GraphicsComponent's and CollisionComponent's! (It will also make lots of copies when doing this).
Imagine if I had hunderds or thousands of components and copying them was not fast...

So, I've used std::vector::reserve instead which makes sure that no allocation will take place.
First, I count how much of each component types will be created. Then I reserve enough memory for each vector. And then I can safely create every entity. No allocations happen during this, yay!
Counting the number of items to reserve is not that easy as it may sound but it didn't take long to implement.

I hope to release source code to this ECS stuff soon! :D
« Last Edit: September 03, 2015, 08:02:58 pm by Elias Daler »
Tomb Painter, Re:creation dev | eliasdaler.github.io | @EliasDaler | Tomb Painter dev log

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6158
  • Thor Developer
    • View Profile
    • Bromeon
Re:creation - a top down action rpg about undeads
« Reply #203 on: September 04, 2015, 08:57:30 am »
The pointer invalidation problem you're talking about is the reason why common ECS implementations store handles, not pointers.

If you have to specifiy an upper bound to the number of components and allocate a fixed number up front, you're severely limiting the usage of your ECS. It may work well for your specific game right now, but you'll have to rethink everything at one point...
« Last Edit: September 04, 2015, 09:00:51 am by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development: first SFML book

Elias Daler

  • Hero Member
  • *****
  • Posts: 570
    • View Profile
    • Blog
    • Email
Re:creation - a top down action rpg about undeads
« Reply #204 on: September 04, 2015, 01:52:37 pm »
@Nexus. Just impelemented handles. They work fine :D
Well, if I don't have an upper bound, this means that a vector may reallocate when some entity is created during the gameplay. This may cause lots of copying which may take a long time causing perfomance drop. The only way to prevent this (that I can think about) is to allocate enough memory up front (and add some additional memory for temporary entities, for example). Are there any other solutions to this problem?
Tomb Painter, Re:creation dev | eliasdaler.github.io | @EliasDaler | Tomb Painter dev log

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32080
    • View Profile
    • SFML's website
    • Email
Re:creation - a top down action rpg about undeads
« Reply #205 on: September 04, 2015, 02:02:00 pm »
Why don't you allocate components individually, and store pointers to them into your vector? It looks weird to use value/copy semantics on components.
Laurent Gomila - SFML developer

Elias Daler

  • Hero Member
  • *****
  • Posts: 570
    • View Profile
    • Blog
    • Email
Re:creation - a top down action rpg about undeads
« Reply #206 on: September 04, 2015, 03:07:06 pm »
Why don't you allocate components individually, and store pointers to them into your vector? It looks weird to use value/copy semantics on components.
Because storing components in one array is better for cache, considering I have to iterate through them in every frame. If you allocate components individually (which I've done before), you get lots of cache misses.

This may seem like an over optimization and I've yet to test speed improvements, but I didn't spend much time making this, so I may throw it away then. :D
Tomb Painter, Re:creation dev | eliasdaler.github.io | @EliasDaler | Tomb Painter dev log

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32080
    • View Profile
    • SFML's website
    • Email
Re:creation - a top down action rpg about undeads
« Reply #207 on: September 04, 2015, 03:21:43 pm »
Quote
This may seem like an over optimization
This is very likely.

The problem now is that it drives a non-negligible part of your design and implementation. So you should really benchmark now, to avoid this kind of issues, and to possibly save one complete rewrite of the system in a near future ;)
Laurent Gomila - SFML developer

Elias Daler

  • Hero Member
  • *****
  • Posts: 570
    • View Profile
    • Blog
    • Email
Re:creation - a top down action rpg about undeads
« Reply #208 on: September 04, 2015, 04:45:29 pm »
The problem now is that it drives a non-negligible part of your design and implementation. So you should really benchmark now, to avoid this kind of issues, and to possibly save one complete rewrite of the system in a near future ;)

Okay, I'll do that very soon, will report the results in this thread :)
Tomb Painter, Re:creation dev | eliasdaler.github.io | @EliasDaler | Tomb Painter dev log

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6158
  • Thor Developer
    • View Profile
    • Bromeon
Re:creation - a top down action rpg about undeads
« Reply #209 on: September 04, 2015, 06:42:49 pm »
The only way to prevent this (that I can think about) is to allocate enough memory up front (and add some additional memory for temporary entities, for example). Are there any other solutions to this problem?
Yeah, of course. std::vector is not the only container in the world.

[Premature optimization] is very likely.
This is probably true for medium-scale games like Re:creation, but the same can be said for many parts of the ECS, maybe even the choice of an ECS design itself. I think it can't hurt to know some alternatives, even if one is not going to use them in a game. But I definitely agree that profiling makes sense.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development: first SFML book

 

anything